Skip to main content
sec0-sdk/instrumentation turns your application methods into audited Sec0 hops. It loads hop metadata from sec0.config.yaml, injects an AgentManager into decorated methods, propagates canonical agent state, and can apply hop-level policy enforcement on top of the underlying business logic.

Startup Paths

Choose one of these initialization paths before any decorators execute:

loadStandardConfig() for the standard app shape

import { loadStandardConfig } from "sec0-sdk/instrumentation";

const config = loadStandardConfig();
This loads sec0.config.yaml, initializes local Sec0 directories, and registers every hop in app.hops.

initializeSec0App() when you only need the registered config

import { initializeSec0App } from "sec0-sdk/instrumentation";

initializeSec0App("./sec0.config.yaml");

initSec0() for low-level bootstrapping

import { initSec0 } from "sec0-sdk/instrumentation";

initSec0({
  localDir: "./.sec0",
  localSignerPath: "./.sec0/keys/ed25519.key",
  tenant: "my-app",
  apiKey: process.env.SEC0_API_KEY,
});
loadStandardConfig(), initializeSec0App(), or initSec0() must run before decorated methods execute.

sec0.config.yaml

The standard config defines application identity, hop metadata, gateway defaults, and local paths:
app:
  tenant: my-app
  environment: dev
  client:
    name: my-agent-system
    version: "1.0.0"
  hops:
    Workflow.orchestrate:
      type: orchestrator
      nodeId: workflow-orch
      orchestratorName: workflow-orch
      orchestratorVersion: "1.0.0"
    OrderAgent.run:
      type: agent
      nodeId: order-agent
      agentName: order-agent
      agentVersion: "1.0.0"
    Workflow.forward:
      type: gateway
      nodeId: workflow-gateway
      gateway: workflow-gateway
      gatewayBaseUrl: https://gateway.example.com
      tenant: my-app
      automation:
        auth: true
        cause: true
        idempotency: true
      enforcement:
        mode: enforce
        deny_on: ["tool_not_in_allowlist"]
        escalate_on: ["tool_not_in_allowlist"]
    EhrFetchTool.invoke:
      type: tool
      nodeId: ehr-agent
      server: fetch
      tool: fetch.get@1.0
      toolRef: mcp://fetch/fetch.get@1.0
    BudgetSkill.run:
      type: skill
      nodeId: finance-skill
      skill: budget-check
      source: openclaw
      enforcement:
        mode: enforce
        deny_on: ["skill_scan_failed"]
        escalate_on: ["skill_scan_failed"]

auth:
  sec0ApiKey: ${SEC0_API_KEY}
  svcToken: ${SVC_TOKEN}

controlPlane:
  sec0Dir: ./.sec0
  localSignerPath: ./.sec0/keys/ed25519.key
  appenderDir: ./.sec0/logs
See Instrumentation Config Reference for the full schema.

Hop Key Resolution

Decorators resolve their hop configuration by key:
  • Explicit: @sec0.agent("MyCustomKey")
  • Inferred: @sec0.agent() resolves to ClassName.methodName
The inferred key must match an entry in app.hops.

Decorators

Every decorated method receives an AgentManager as its last parameter.

@sec0.agent() and @sec0.orchestrator()

Use these for reasoning and coordination hops:
import { sec0, AgentManager } from "sec0-sdk/instrumentation";

class OrderAgent {
  @sec0.agent()
  async run(ctx: any, input: { orderId: string }, manager: AgentManager) {
    manager.agent.setState({ order_id: input.orderId });
    manager.agent.setMetadata({ received_at: Date.now() });
    manager.agent.objective("Process order and validate payment");

    const headers = manager.getAgentStateHeaders();
    await fetch("https://api.example.com/process", { method: "POST", headers });

    return { ok: true };
  }
}

class Workflow {
  @sec0.orchestrator()
  async orchestrate(ctx: any, input: any, manager: AgentManager) {
    manager.agent.objective("Coordinate order fulfillment workflow");
    manager.agent.setState({ workflow_id: input.workflowId });

    await manager.invoke("OrderAgent.run", {
      orderId: input.orderId,
    });

    return { ok: true };
  }
}

@sec0.gateway()

Gateway hops are the cleanest way to centralize bridge defaults in sec0.config.yaml:
import { sec0, AgentManager } from "sec0-sdk/instrumentation";
import { callToolViaGateway } from "sec0-sdk/middleware";

class Router {
  @sec0.gateway()
  async forward(params: any, manager: AgentManager) {
    return await callToolViaGateway({
      ...params,
      agentState: manager.agent.snapshot(),
    });
  }
}

@sec0.server(), @sec0.middleware(), @sec0.tool(), and @sec0.skill()

Use the remaining decorators when you want audit and state tracking on specific execution layers:
class FetchTool {
  @sec0.tool()
  async invoke(params: any, manager: AgentManager) {
    manager.agent.setState({ endpoint_kind: "api" });
    return await fetch(params.args.url);
  }
}

class BudgetSkill {
  @sec0.skill()
  async run(params: any, manager: AgentManager) {
    manager.agent.setMetadata({ source: "openclaw" });
    return { policy_violation: "skill_scan_failed" };
  }
}

AgentManager

AgentManager is the primary integration surface inside a decorated method.
manager.agent.setState({ order_id: "A-100", status: "processing" });
manager.agent.setMetadata({ model: "gpt-4o", temperature: 0.7 });
manager.agent.objective("Find available appointments within 10 miles");
const state = manager.agent.snapshot();

Header Propagation

const headers = manager.getAgentStateHeaders();
const merged = manager.getAgentStateHeaders(existingHeaders);

Cross-Hop Invocation

await manager.invoke("PaymentsAgent.process", {
  orderId: "A-100",
  amount: 99.99,
});
If the target hop has remoteUrl, the SDK issues an HTTPS POST. Otherwise, register a local handler:
import { registerLocalHopHandler } from "sec0-sdk/instrumentation";

registerLocalHopHandler("PaymentsAgent.process", (params, agentState) => {
  return paymentsAgent.process({ ...params, agentState });
});

Hop Automation Flags

Each hop can enable automation flags for common cross-cutting concerns:
app:
  hops:
    Router.forward:
      type: gateway
      nodeId: router
      gateway: main-gateway
      gatewayBaseUrl: https://gateway.example.com
      automation:
        ap2: true
        identityContext: true
        idempotency: true
        auth: true
        cause: true

Hop-Level Policy Enforcement

Decorators can now enforce policy directly from hop config. This is useful when the hop itself returns or throws a policy outcome and you want consistent deny and escalation handling in the audit layer. Example:
app:
  hops:
    BudgetSkill.run:
      type: skill
      nodeId: finance-skill
      skill: budget-check
      enforcement:
        mode: enforce
        deny_on: ["skill_scan_failed"]
        escalate_on: ["skill_scan_failed"]
        policy_scope: auto
        refresh_ttl_ms: 60000
With this enabled, decorated hops can trigger policy outcomes by:
  • returning policy_breaches: string[]
  • returning policy_violation: string
  • throwing an error that carries denial_reason
The decorator converts the outcome into a POLICY_DENIED error, appends the signed audit envelope, and includes escalation_id and escalation_status when escalation is configured.

Utility Functions

import {
  generateRunRef,
  generateTraceId,
  generateSpanId,
  seedSec0Run,
  getConfig,
  getSec0AppConfig,
  getSec0Directories,
} from "sec0-sdk/instrumentation";

const runId = generateRunRef();
const traceId = generateTraceId();
const spanId = generateSpanId();

seedSec0Run(runId, () => {
  // Any decorated hop called in here inherits the seeded run id
});