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(),
});
}
}
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();
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
});