CounterAudit Integration
api.counteraudit.io against Arc testnet, verified against a real sealed packet. Outcomes the payer signed go through their own connector, below, with no allowlist and no oracle token. The older relay is built: add outcome and payment_tx_hash to an ingest and the result is attested to the oracle, but only for an org CounterAudit allowlists. Its production deployment allowlists none, because the outcome is the ingesting org's word rather than something CounterAudit checked. The settlement hash is required because the payment is the credential — the oracle re-reads that transaction from the chain rather than trusting the caller. The outcome is recorded because CounterAudit presents an oracle token; with neither a token nor the payer's signature, the payment would be credited and no outcome recorded.Adding Sigvara identity to CounterAudit requires one field: agent_did. When CounterAudit receives an ingest call with a valid agent_did, it queries the live on-chain identity and reputation score and seals both inside the AES-GCM-encrypted, RFC 3161-timestamped packet. The reputation score is frozen at the moment of the action — it does not change retroactively even if the agent is later slashed.
The Minimal Change
If you are already using CounterAudit, add one field to your existing ingest payload:
// Before
{ connector_id: 'my-agent', raw_event: action }
// After — add agent_did
{ connector_id: 'my-agent', agent_did: myAgent.did, raw_event: action }
TypeScript Example
import { SigvaraAgent } from '@sigvara/protocol-sdk';
const myAgent = new SigvaraAgent({
privateKey: process.env.AGENT_ED25519_SEED,
agentAddress: process.env.AGENT_ADDRESS,
chainId: 5042002,
});
async function auditAction(action: object) {
const res = await fetch('https://api.counteraudit.io/v1/audit/ingest', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
connector_id: 'my-agent',
agent_did: myAgent.did,
raw_event: action,
}),
});
return res.json();
}
What Gets Sealed
When CounterAudit receives an ingest call with a valid agent_did, it reads the following fields from the Sigvara contracts at ingest time and embeds them inside the sealed packet:
"agent_did_hash": "0xef55a65a321380b8e74bb38087a4d3ddfcb5789f86b456317a2a47950dcceca9",
"agent_chain_id": 5042002,
"agent_reputation_score": 47,
"agent_identity_status": "Active",
"agent_identity_verified": true,
"agent_enriched_at": "2026-06-30T16:33:39.381Z"
Verifying a Sealed Packet
const res = await fetch(`https://api.counteraudit.io/v1/audit/verify/${packetId}`, {
headers: { 'Authorization': `Bearer ${CA_API_KEY}` }
});
const { packet } = await res.json();
// Sigvara fields are in the decrypted body
console.log(packet.agent_did); // did:sigvara:5042002:0x...
console.log(packet.agent_reputation_score); // Score at time of action
console.log(packet.agent_identity_status); // PendingBond | Active | Suspended | Slashed
Python Example
import requests
def audit_action(agent_did: str, action: dict, ca_api_key: str):
return requests.post(
"https://api.counteraudit.io/v1/audit/ingest",
headers={
"Authorization": f"Bearer {ca_api_key}",
"Content-Type": "application/json",
},
json={
"connector_id": "my-agent",
"agent_did": agent_did,
"raw_event": action,
},
).json()
Feeding Reputation Back (attestations)
The integration also works in reverse. Add an outcome of "success" or "failure", together with the payment_tx_hash that paid for the work, to an ingest for a registered agent, and CounterAudit reports it to the Sigvara reputation oracle after the event is sealed, for orgs it allowlists (none in production since 30 October 2026; see the status note above). Those attestations drive the agent's Success Rate and Fee Activity factors, so reported work builds reputation, not just records it. Only successfully sealed, non-duplicate events count; a rejected ingest never moves a score.
// Same ingest, plus an outcome and the payment behind it: feeds the agent's live score
{
connector_id: 'my-agent',
agent_did: myAgent.did,
outcome: 'success', // or 'failure'
payment_tx_hash: '0x...', // the transaction that paid for this work
raw_event: action,
}
Payer-signed outcomes
Live since 1 November 2026. An outcome the payer signed (ADR 0006) goes through its own connector, sigvara-payment-outcome-v1. Its raw_event is exactly the body the oracle's POST /attest takes: the agent's didHash, the settlement payment.txHash, and the payerOutcome that signPaymentOutcome in the SDK returns.
{
connector_id: 'sigvara-payment-outcome-v1',
raw_event: {
didHash: '0x84...',
payment: { txHash: '0x...' },
payerOutcome, // from signPaymentOutcome(payerWallet, ...)
},
}
CounterAudit checks the signature against the payer with the SDK's verifyPaymentOutcome, seals the record whole, and forwards it with no token to each operator in its SIGVARA_PAYER_OUTCOME_OPERATORS. The ingest response returns each operator's answer as forwarded. Sending the same record again asks only the operators that have not taken it, and CounterAudit posts to any one operator at most 30 times a minute. It is a courier and a sealer here, not an attester: each operator checks the payment and the signature itself and trusts the payer, not CounterAudit. The operators take "delivered" only; "not delivered" waits for a challenge process.
See the Reputation Model for how each factor is computed and where its signal comes from.
Why the Sealed Packet Matters
The reputation score is frozen at the moment of the action. If an agent is slashed next month, every audit record from before the slash still shows what their reputation was at the time. The historical record does not rewrite itself — the RFC 3161 timestamp and AES-GCM seal together guarantee it. This is the forensic property that makes Sigvara-enriched audit records legally meaningful.