{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreifs2n3erv7o3u7duut3hdweksl67azfjaf6avl46e5xsessyqymte",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mp5tfkjvmpo2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreienetmehdp63eb47fvk4qhveopr7e37sosipfmbs4r5xmspkier24"
    },
    "mimeType": "image/webp",
    "size": 57938
  },
  "path": "/telleroutlook/your-ai-agent-called-a-tool-can-you-prove-it-followed-the-rules-2bgn",
  "publishedAt": "2026-06-26T01:26:57.000Z",
  "site": "https://dev.to",
  "tags": [
    "agents",
    "ai",
    "architecture",
    "security",
    "packages/aep",
    "packages/otel-exporter",
    "@wasmagent"
  ],
  "textContent": "#  Your AI agent called a tool. Can you prove it followed the rules?\n\nYour agent just wrote a file. You have logs. But can you answer this:\n\n> Was the policy gate applied _before_ the tool ran — or after?\n\nLogs can't tell you that. Here's how we solved it.\n\n##  The gap in current agent frameworks\n\nMost frameworks give you a log line like:\n\n\n\n    [2026-07-07T09:00:01Z] tool:fs_write path=/tmp/report.txt status=ok\n\n\nThat tells you the tool ran. It doesn't tell you:\n\n  * Whether a policy evaluated the call first\n  * What the pre-state looked like before the write\n  * Whether the agent was within its token and risk budget\n  * Which agent in a delegation chain authorized this\n\n\n\nFor a hobby project, that's fine. For anything touching real data, it's not.\n\n##  AEP: structured proof, not a log stream\n\nWasmAgent's `@wasmagent/aep` package records every tool call as an `ActionEvidence` object — Zod-validated, schema-versioned, with pre/post state digests baked in.\n\n\n\n    import { AEPEmitter } from \"@wasmagent/aep\";\n\n    const emitter = new AEPEmitter({\n      run_id: \"run-abc123\",\n      repo_commit: \"5c1102f\",\n      model_id: \"claude-sonnet-4-6\",\n    });\n\n    // Before tool execution:\n    emitter.addAction({\n      tool_name: \"fs_write\",\n      state_changing: true,\n      capability_decision: {\n        capability: \"fs_write\",\n        subject: \"agent:run-abc123\",\n        resource: \"/tmp/report.txt\",\n        decision: \"allow\",\n        reason_code: \"policy:default-v1\",\n      },\n      precondition_digest: \"sha256:a1b2c3...\",\n      input_taint_labels: [\"user_provided\"],\n    });\n\n    // After tool execution:\n    emitter.addAction({\n      tool_name: \"fs_write\",\n      state_changing: true,\n      post_state_digest: \"sha256:d4e5f6...\",\n    });\n\n    emitter.setBudgetLedger({\n      token_budget: { limit: 4000, spent: 142 },\n      risk_budget:  { limit: 1.0,  spent: 0.2 },\n    });\n\n    const record = emitter.build();\n\n\nThe `capability_decision` is part of the same record as the action — not a separate log entry that could be reordered or dropped.\n\n##  OTel spans for everything else\n\nFor real-time observability, AEP also emits named OpenTelemetry spans:\n\n\n\n    import { AEP_SPAN_NAMES } from \"@wasmagent/otel-exporter\";\n\n    // Plug into any OTel collector:\n    AEP_SPAN_NAMES.TOOL_CALL       // \"tool.call\"\n    AEP_SPAN_NAMES.POLICY_CHECK    // \"policy.check\"\n    AEP_SPAN_NAMES.SANDBOX_EXEC    // \"sandbox.exec\"\n    AEP_SPAN_NAMES.VERIFIER_CHECK  // \"verifier.check\"\n    AEP_SPAN_NAMES.LLM_GENERATE    // \"llm.generate\"\n    AEP_SPAN_NAMES.MCP_REQUEST     // \"mcp.request\"\n    // + 3 more\n\n\nThe spans go to Grafana/Jaeger/etc. The `AEPRecord` is what you keep for audit and training data.\n\n##  Multi-agent: delegation chain\n\nIn a single-agent setup, this is useful. In a multi-agent setup — orchestrator delegates to a subagent — it becomes essential:\n\n\n\n    run_context: {\n      agent_id: \"orchestrator\",\n      subagent_id: \"coder-agent\",\n      delegation_chain: [\"orchestrator\", \"planner\", \"coder-agent\"],\n      scope_lease_id: \"lease-xyz\",  // ← subagent can only do what parent granted\n    }\n\n\n##  Try it\n\n\n    git clone https://github.com/WasmAgent/wasmagent-js\n    bun test packages/aep/src/\n\n\n**Next in this series:** MCP Trust Pack — the gateway layer that enforces policy before tools execute.\n\n**Code:** packages/aep · packages/otel-exporter",
  "title": "Your AI agent called a tool. Can you prove it followed the rules?"
}