Developers

Integrate an agent in 5 minutes

Traces2
Approved1
Rejected1
Mode0G

Argus wraps your agent in an accountability layer: structured traces, on-chain mandate enforcement, cryptographic evidence sealing, and replayable proof packages. This guide shows the full integration path from trace construction to tamper verification.

STEP 01

Build a structured trace

Every agent action must be captured as an ArgusTrace before execution. The trace records the full decision path: what the agent observed, what it remembered, what it inferred, and what it proposed. All fields are deterministic — same inputs produce same hash.

// Monorepo workspace package — not yet on npm
import { canonicalize, traceRoot, tracePayloadForHash } from "@argus/shared";
// Monorepo workspace package — not yet on npm
import { LocalStorageFallbackAdapter } from "@argus/storage-0g";

// Build a structured trace for the agent's proposed action
const trace: ArgusTrace = {
  schemaVersion: "argus.trace.v1",
  traceId: crypto.randomUUID(),
  createdAt: new Date().toISOString(),
  chainId: 16661,
  mandateId: "mandate-treasury-ops-1",
  agentId: "agent-executor-7",
  observation: { source: "market-feed", content: "ETH/USDC -4.2% in 1h" },
  memory: { promptInjectionDetected: false, relevantMemory: ["rebalance on >3% swing"] },
  inference: { summary: "Rebalance threshold exceeded", riskSignals: [] },
  proposedAction: {
    actionType: "SWAP", target: "0x...", recipient: "0x...",
    asset: "0x...", amount: "500000000", // 500 USDC
    actionId: "0x..."
  },
  policyCheck: { verdict: "approved", violationCodes: [], checks: [] },
  execution: { status: "approved" },
  penalty: { slashed: false, complianceScoreBefore: 800, complianceScoreAfter: 805 },
  proof: { canonicalHash: "0x...", storageURI: "", committedTraceRoot: "0x..." }
};
STEP 02

Canonicalise, hash, store

Canonical JSON serialisation ensures identical bytes for identical data. The trace root is keccak256(canonicalize(tracePayloadForHash(trace))). The storage URI returned by the adapter is included in the on-chain proposal.

// Canonicalise and hash the trace
const payload = tracePayloadForHash(trace);
const root = traceRoot(payload); // keccak256 of canonical JSON

// Store in 0G Storage (or local fallback)
const storage = new LocalStorageFallbackAdapter("./traces");
const receipt = await storage.putJSON(trace.traceId, trace);

// receipt.uri  → "local://traces/agent-executor-7-a1b2c3d4.json"
// receipt.root → "0xabcd..." (matches root computed above)
STEP 03

Route through ActionGate

submitAction() evaluates the proposal against all 6 mandate clauses on-chain. If any clause fails, the action is rejected before execution, the bond is slashed, andActionRejected is emitted with a violation bitmap. Use preview() to simulate without writing state.

import { ActionGate__factory } from "./typechain";

const actionGate = ActionGate__factory.connect(ACTION_GATE_ADDRESS, signer);

const proposal = {
  mandateId: BigInt(1),
  agentId: BigInt(7),
  actionId: trace.proposedAction.actionId,
  actionType: ethers.encodeBytes32String("SWAP"),
  target: trace.proposedAction.target,
  recipient: trace.proposedAction.recipient,
  asset: trace.proposedAction.asset,
  amount: BigInt(trace.proposedAction.amount),
  traceRoot: root,       // keccak256 of canonical trace
  storageURI: receipt.uri
};

const tx = await actionGate.submitAction(proposal);
const receipt = await tx.wait();

// Emits ActionApproved or ActionRejected
// ActionRejected includes: reasonBitmap, slashed (wei)
Violation bitmap flags
VIOLATION_AMOUNT
1 << 0proposal.amount > mandate.maxAmount
VIOLATION_TARGET
1 << 1target not in mandate.allowedTargets
VIOLATION_RECIPIENT
1 << 2recipient in mandate.blockedRecipients
VIOLATION_ACTION_NOT_ALLOWED
1 << 3actionType not in mandate.allowedActionTypes
VIOLATION_ACTION_FORBIDDEN
1 << 4actionType in mandate.forbiddenActionTypes
VIOLATION_ASSET
1 << 5proposal.asset != mandate.asset
STEP 04

Verify the proof package

After the action is committed on-chain, any party can independently verify the evidence. Fetch the stored trace from the storage URI, recompute the root, and diff against thecommittedTraceRoot on-chain. A root mismatch proves the stored evidence was tampered with after commitment.

// Monorepo workspace package — not yet on npm
import { verifyTrace, buildProofPackage } from "@argus/shared";

// Fetch the stored trace from the storage URI
const storedTrace = await storage.getJSON(receipt.uri);

// Verify: recompute root, diff against committedTraceRoot
const result = verifyTrace(storedTrace, trace.proof.committedTraceRoot);

if (result.status === "valid") {
  console.log("Trace root matches committed value — evidence intact");
} else if (result.status === "mismatch") {
  // result.diff contains field-level diffs: path, expected, actual
  console.error("Tampering detected:", result.diff);
}

// Build exportable proof package for shareable /proof/:root page
const pkg = buildProofPackage({ trace, proof: proofPanelData });

Browser verification (no backend required)

The shared package exports browser-safe helpers that use the Web Crypto API. No server, no proxy, no trust requirement. Paste a trace, get a verdict.

// Monorepo workspace package — not yet on npm
// Browser-safe — no Node.js crypto required
import { verifyTraceInBrowser } from "@argus/shared";

const result = await verifyTraceInBrowser(traceJson, committedRoot);

Local fallback vs. 0G Storage

The storage adapter interface is stable. Swapping from local fallback to 0G Storage requires only a constructor change. All upstream code — hashing, commitment, verification — is unchanged.

// Monorepo workspace package — not yet on npm
// Swap local fallback for 0G Storage adapter when ready
// No other code changes required

// Current: local filesystem
import { LocalStorageFallbackAdapter } from "@argus/storage-0g";
const storage = new LocalStorageFallbackAdapter("./traces");

// Planned: ZeroGStorageAdapter (adapter interface defined, 0G integration roadmap)
import { ZeroGStorageAdapter } from "@argus/storage-0g";
const storage = new ZeroGStorageAdapter({ rpc: "https://rpc.0g.ai", key: process.env.KEY });

What Argus does not do

Execute transactions — ActionGate blocks or approves, your agent executes.
Generate agent strategy — Argus enforces mandates, not business logic.
Store secrets — trace JSON is plaintext evidence, not encrypted vault.
Guarantee TEE execution — attestation is currently simulated; 0G Compute is roadmap.