Integration
AI Framework Integration
The pattern is the same in every framework: generate a Countersig DID at agent startup, then include it in every CounterAudit ingest call. The DID travels with the agent's actions, creating a cryptographically-linked audit trail tied to an on-chain identity.
Prerequisite: Your agent must be registered on Countersig. Follow the Quickstart first, then set
AGENT_DID in your environment.Framework Examples
LangChain
AutoGen
CrewAI
Generic Node.js
import { Tool } from 'langchain/tools';
import { CountersigAgent } from '@countersig/protocol-sdk';
const csAgent = new CountersigAgent({
privateKey: process.env.AGENT_ED25519_SEED,
agentAddress: process.env.AGENT_ADDRESS,
chainId: 46630,
});
// Wrap any LangChain tool to add Countersig auditing
function withCountersig(tool: Tool): Tool {
const originalCall = tool.call.bind(tool);
tool.call = async (input: string) => {
const result = await originalCall(input);
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: 'langchain-agent',
agent_did: csAgent.did,
raw_event: { tool: tool.name, input, output: result },
}),
});
return result;
};
return tool;
}
import autogen
import requests, os
AGENT_DID = os.environ["AGENT_DID"]
CA_API_KEY = os.environ["CA_API_KEY"]
def audit(action_type: str, content: str):
requests.post(
"https://api.counteraudit.io/v1/audit/ingest",
headers={"Authorization": f"Bearer {CA_API_KEY}", "Content-Type": "application/json"},
json={
"connector_id": "autogen-agent",
"agent_did": AGENT_DID,
"raw_event": {"type": action_type, "content": content},
},
)
class AuditedAssistant(autogen.AssistantAgent):
def generate_reply(self, messages=None, sender=None, **kwargs):
reply = super().generate_reply(messages=messages, sender=sender, **kwargs)
if reply:
audit("reply", str(reply))
return reply
from crewai import Agent, Task, Crew
from crewai.tools import BaseTool
import requests, os
AGENT_DID = os.environ["AGENT_DID"]
CA_API_KEY = os.environ["CA_API_KEY"]
class AuditedTool(BaseTool):
name: str = "audited_tool"
description: str = "Runs a task and audits it with Countersig identity"
def _run(self, input_data: str) -> str:
result = f"Processed: {input_data}"
requests.post(
"https://api.counteraudit.io/v1/audit/ingest",
headers={"Authorization": f"Bearer {CA_API_KEY}"},
json={
"connector_id": "crewai-agent",
"agent_did": AGENT_DID,
"raw_event": {"tool": self.name, "input": input_data, "output": result},
},
)
return result
import { CountersigAgent } from '@countersig/protocol-sdk';
// Initialize once at startup
const csAgent = new CountersigAgent({
privateKey: process.env.AGENT_ED25519_SEED,
agentAddress: process.env.AGENT_ADDRESS,
chainId: 46630,
});
// Call before or after any significant agent action
async function auditAction(eventType: string, payload: object) {
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: csAgent.did,
raw_event: { type: eventType, ...payload },
}),
});
}
The Universal Pattern
Regardless of framework, the integration follows the same three steps:
- Initialize once at startup. Create a
CountersigAgentinstance from your stored Ed25519 seed and agent address. - Include the DID in every audit call. Pass
agent_did: csAgent.didin every CounterAudit ingest payload. - Never include the private key in the payload. The DID is a public identifier. The private key is only used to sign challenges when a peer requests authentication.