Skip to main content
This quickstart uses the current developer entrypoints in sec0-sdk:
  • sec0-sdk/middleware for in-process tool enforcement
  • sec0-sdk/instrumentation for hop decorators and agent-state propagation
  • sec0-sdk/guard for outbound allow, redact, block, and escalate decisions
  • sec0-sdk/middleware plus sec0-sdk/gateway for cross-network tool calls

Prerequisites

  • Node.js >= 20
  • An Ed25519 signing key
  • A local policy.yaml
  • Optional: a Sec0 API key when you switch to hosted policy or approvals

1. Install the SDK

npm install sec0-sdk

2. Generate a Signing Key

mkdir -p .sec0/keys
openssl rand -base64 32 > .sec0/keys/ed25519.key
Store your signing key securely. If you keep the key outside default safe directories (.sec0/keys, keys, config/keys, .sec0/secrets, secrets), set SEC0_SIGNER_KEY_DIRS.

3. Create a Minimal policy.yaml

Start with a local, observe-mode policy:
tenant: my-app
default_retention: "30d"

signing:
  enabled: true
  key_ref: "file://./.sec0/keys/ed25519.key"

observability:
  otlp_endpoint: "http://127.0.0.1:4318"
  sample:
    success: 1
    error: 1

tools:
  allowlist: ["*"]
  deny_if_unpinned_version: false

privacy:
  redact_outputs: false
  store_raw_payloads: false
  artifact_retention:
    public: "30d"
    pii: "30d"
    phi: "30d"

side_effects:
  require_idempotency_key: false
  max_retries: 0

enforcement:
  deny_on: []
  circuit_breakers:
    error_rate_pct: 100
    p95_latency_ms: 0

sec0_export:
  enabled: false
  bucket_uri: "gs://unused-local-dev"

4. Wrap a Tool Server with sec0LocalMiddleware

For a first integration, use the local preset. It keeps policy, runtime decisions, approvals, and audit writes on-device.
import fs from "node:fs";
import { parsePolicyYaml } from "sec0-sdk/policy";
import { LocalDevSigner } from "sec0-sdk/signer";
import { sec0LocalMiddleware } from "sec0-sdk/middleware";

const server = createYourMcpServer();
const policy = parsePolicyYaml(fs.readFileSync("./policy.yaml", "utf8"));

sec0LocalMiddleware({
  policy,
  signer: LocalDevSigner.fromKeyRef(policy.signing.key_ref),
  otel: {
    endpoint: policy.observability.otlp_endpoint,
    serviceName: "orders-mcp",
    serviceVersion: "1.0.0",
    environment: "dev",
    tenant: policy.tenant,
  },
  sec0: { dir: ".sec0", retentionDays: 30 },
  telemetry: { enabled: false },
})(server);
When you need hosted policy, approvals, or remote runtime evaluation, switch the same server to sec0HostedMiddleware. See Middleware.

5. Register Hop Metadata in sec0.config.yaml

Instrumentation uses sec0.config.yaml to resolve hop identity, gateway defaults, and local storage:
app:
  tenant: my-app
  environment: dev
  client:
    name: my-agent-runtime
    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"
    Gateway.forward:
      type: gateway
      nodeId: workflow-gateway
      gateway: sec0-gateway
      gatewayBaseUrl: https://gateway.example.com
      automation:
        auth: true
        cause: true
        idempotency: true

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

controlPlane:
  sec0Dir: ./.sec0
  localSignerPath: ./.sec0/keys/ed25519.key
  appenderDir: ./.sec0/logs

6. Initialize Decorators and Propagate Agent State

Decorators give you stable nodeId, runId, state propagation, and signed audit envelopes across agent hops:
import { initializeSec0App, sec0, AgentManager } from "sec0-sdk/instrumentation";

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

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

    const headers = manager.getAgentStateHeaders();
    await fetch("https://api.example.com/process-order", {
      method: "POST",
      headers,
      body: JSON.stringify({ orderId: input.orderId }),
    });

    return { ok: true };
  }
}

class Workflow {
  @sec0.orchestrator()
  async orchestrate(ctx: any, input: any, manager: AgentManager) {
    manager.agent.objective("Plan and execute the order workflow safely.");
    await manager.invoke("OrderAgent.run", {
      orderId: input.orderId,
    });

    return { ok: true };
  }
}

7. Add Guard Checks for Outbound Messages or API Calls

Use sec0-sdk/guard when the action is not naturally wrapped by the middleware, or when you want a simple allow, redact, block, and escalate API in application code:
import { createSec0Guard } from "sec0-sdk/guard";

const guard = createSec0Guard({
  mode: "standalone",
  provider: {
    local: {
      policy: {
        defaultOutcome: "allow",
        rules: [
          {
            kind: "message_outbound",
            target: "discord:supplier",
            outcome: "block",
            reason: "supplier_messages_require_review",
          },
        ],
      },
    },
  },
});

await guard.execute(
  {
    kind: "message_outbound",
    target: "discord:supplier",
    content: outboundMessage,
  },
  async () => sendToSupplier(outboundMessage),
);
See Guard API for dashboard and hybrid modes, redaction, and approvals transport wiring.

8. Route Cross-Network Tool Calls Through the Gateway

Use the bridge helper when tool execution crosses a process or network boundary:
import { callToolViaGateway } from "sec0-sdk/middleware";

const result = await callToolViaGateway({
  gatewayBaseUrl: "https://gateway.example.com",
  server: "payments-mcp",
  toolAtVersion: "charge@1.0",
  args: { amount: 4999, currency: "usd" },
  authHeader: `Bearer ${process.env.SVC_TOKEN}`,
  cause: { traceId: ctx.traceId, spanId: ctx.spanId },
  agentState: manager.agent.snapshot(),
  timeoutMs: 15_000,
});
Use Gateway Bridge for client options and Network Gateway to deploy the server side.

9. Switch to Hosted Policy and Approvals When Ready

Replace the local preset with the hosted preset when you want control-plane policy sync, escalation creation, or remote runtime evaluation:
import { sec0HostedMiddleware } from "sec0-sdk/middleware";
import { LocalDevSigner } from "sec0-sdk/signer";

sec0HostedMiddleware({
  policy: {
    source: "control-plane",
    level: "middleware",
    scope: "auto",
    refreshTtlMs: 60_000,
  },
  auth: { apiKey: process.env.SEC0_API_KEY! },
  signer: LocalDevSigner.fromKeyRef("file://./.sec0/keys/ed25519.key"),
  otel: {
    endpoint: "http://127.0.0.1:4318",
    serviceName: "orders-mcp",
    serviceVersion: "1.0.0",
    environment: "dev",
    tenant: "my-app",
  },
  sec0: { dir: ".sec0", retentionDays: 30 },
})(server);
Then configure enforcement.escalate_on plus security.side_effects.human_escalation and connect the approvals bridge. See Approvals & Escalations.

10. Verify

Use the Verify & Troubleshoot checklist to confirm each layer is working.

What’s Next?

Middleware

Wrap tool servers and choose local vs hosted presets

Guard API

Gate outbound messages, tool calls, and APIs

Instrumentation

Register hops, decorators, and propagation

Gateway

Add network-edge enforcement and brokering