API Contracts
Canonical execution contract - invokeAgent, ToolCallEnvelope, ToolResultEnvelope, DecisionRecord envelope, and RunContext propagation.
ContextOS standardizes its runtime through a single canonical execution contract. The envelopes below are the source of truth for runtime behavior; prose elsewhere is a blueprint unless it links here.
Published validation artifacts:
| Contract | Schema |
|---|---|
RunContext | /schemas/run-context.v1.schema.json |
invokeAgent | /schemas/invoke-agent.v1.schema.json |
CompiledContext | /schemas/compiled-context.v1.schema.json |
ToolEnvelope | /schemas/tool-envelope.v1.schema.json |
DecisionRecord | /schemas/decision-record.v1.schema.json |
ReplayPacket | /schemas/replay-packet.v1.schema.json |
Canonical execution contract
invokeAgent(request_envelope, run_context)
→ compile(packs, request, run_context) → CompiledContext
→ loop {
planner(CompiledContext) → Plan
critic.verify(Plan) → ok | replan | reject
executor(Plan, ToolGateway) → step_results, evidence
critic.score(step_results) → accept | retry | replan | escalate
consolidate(effects, evidence) → memory_proposals
}
→ DecisionRecord(evidence_refs, approvals, controls_active, trace_id)Run Context
The Run Context is the state container carried through every layer and every contract. Every envelope below carries it (or a reference to it).
{
"run_id": "run_a1b2c3d4e5f60718",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"session_id": "sess_42f1",
"tenant_id": "tenant_acme_prod",
"user": {
"user_id": "usr_771",
"delegation": {
"auth_type": "oauth2",
"scopes": ["orders.read", "payments.refund"],
"subject": "u:user:771",
"token_ref": "tok_user_7a"
}
},
"agent": {
"agent_id": "agt_support",
"agent_urn": "agent:contextos/support-refund@1.2.0",
"workload_identity": "spiffe://contextos/agents/support",
"role": "support_ops",
"token_ref": "tok_agent_92",
"lifecycle": "active",
"principal_chain": [
{ "kind": "user", "id": "usr_771", "tenant_id": "tenant_acme_prod" },
{ "kind": "agent", "id": "agent:contextos/support-refund@1.2.0", "tenant_id": "tenant_acme_prod" }
],
"identity_claim": {
"version": "ctxid/1",
"sub": "agent:contextos/support-refund@1.2.0",
"run_id": "run_a1b2c3d4e5f60718",
"tenant_id": "tenant_acme_prod",
"scopes": ["tools:read", "tools:write", "a2a:send"],
"kid": "kid_ctxos_support_2026_05",
"claim_hash": "sha256:..."
}
},
"intent": "support.refund",
"locale": "en-IN",
"safety_mode": "delegated",
"run_budget": {
"total_tokens": 12000,
"bucket_tokens": { "policy": 1800, "tool": 1500, "evidence": 3500, "memory": 1500, "business": 1500, "session": 2200 },
"max_tool_calls": 8,
"max_replan_attempts": 2,
"wall_clock_ms": 30000,
"max_cost_cents": 25.0
},
"metadata": {}
}Try it: live envelope builder
Toggle the mode and safety_mode below to see the invokeAgent envelope rebuild live, alongside the runtime implications.
- Streaming. Bidirectional event stream; tool calls progress live to the client.
- Delegated identity. Tool Gateway requires a valid user_delegation_token_ref on every toolCall. Per-call evidence captured.
{
"request_id": "req_9f3a12",
"session_id": "sess_42f1",
"tenant_id": "tenant_acme_prod",
"user": {
"user_id": "usr_771",
"delegation": {
"auth_type": "oauth2",
"scopes": [
"orders.read",
"payments.refund"
],
"subject": "u:user:771"
}
},
"agent": {
"agent_id": "agt_support",
"workload_identity": "spiffe://contextos/agents/support"
},
"context_pack_refs": [
"ctxpack.support@5.2.0"
],
"input": {
"intent": "support.refund",
"message": "Refund order ord_881 for INR 4200",
"channel": "app_chat",
"locale": "en-IN",
"context": {
"refund_amount": 4200,
"identity_verified": true
}
},
"mode": "stream",
"runtime": {
"plan_timeout_ms": 15000,
"max_tool_calls": 8,
"max_cost_cents": 25
},
"trace": {
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"trace_flags": "01"
}
}invokeAgent envelope
The single entry point for the runtime.
{
"request_id": "req_9f3a12",
"session_id": "sess_42f1",
"tenant_id": "tenant_acme_prod",
"user": {
"user_id": "usr_771",
"delegation": { "auth_type": "oauth2", "scopes": ["orders.read", "payments.refund"], "subject": "u:user:771" }
},
"agent": {
"agent_id": "agt_support",
"agent_urn": "agent:contextos/support-refund@1.2.0",
"workload_identity": "spiffe://contextos/agents/support",
"role": "support_ops",
"identity_claim": {
"sub": "agent:contextos/support-refund@1.2.0",
"run_id": "run_a1b2c3d4e5f60718",
"tenant_id": "tenant_acme_prod",
"scopes": ["tools:read", "tools:write"],
"claim_hash": "sha256:..."
}
},
"context_pack_refs": [
"ctxpack.support@5.2.0",
"decision-catalog.support@2.1.0"
],
"input": {
"intent": "support.refund",
"message": "Refund order ord_881",
"channel": "app_chat",
"locale": "en-IN"
},
"mode": "stream",
"runtime": {
"plan_timeout_ms": 15000,
"max_session_duration_ms": 14400000,
"max_tool_calls": 8,
"max_payload_bytes": 1048576,
"max_cost_cents": 25.0
},
"attachments": [
{ "artifact_id": "art_invoice_881", "media_type": "application/pdf", "sha256": "2f9cc0...", "uri": "s3://tenant-acme-prod/invoices/881.pdf" }
],
"trace": {
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"trace_flags": "01"
}
}Field reference
| Field | Required | Description |
|---|---|---|
request_id | yes | globally unique request identifier |
session_id | optional | per-session execution scope; absent → ephemeral run |
tenant_id | yes | tenant boundary for policy, data, and tool auth |
user.delegation | required for delegated and destructive modes | OAuth-style on-behalf-of token reference |
agent.agent_urn | yes | versioned agent subject: agent:contextos/<slug>@<version> |
agent.workload_identity | yes | SPIFFE-style URI for the executing workload |
agent.identity_claim | yes for governed agent execution | signed, short-lived run or hop claim; audit should expose the claim_hash, not raw secrets |
context_pack_refs[] | yes (≥1) | pinned pack versions; the runtime refuses unpinned refs |
input.intent | yes | canonical intent in the Intent-Task Catalog |
mode | yes | stream / batch / long_running |
runtime.* | yes | budget hints; the runtime materializes these into the RunContext.run_budget |
trace | yes | W3C Trace Context — propagated through every span |
Execution modes
stream— bidirectional event stream for interactive planning/tool steps.batch— single response envelope for non-interactive jobs.long_running— durable session with progress events and heartbeat TTL for hour-scale workflows.
Timeout and long-running guidance
- Planner timeout: 5–30 s by task class.
- Tool step timeout: adapter-specific (2–120 s typical).
- Long-running session timeout: up to hours with heartbeat renewal.
- Hard-stop behavior: fail closed with a resumable checkpoint and a structured
escalateverdict.
Payload limits and attachments
- Keep envelope metadata small and stable.
- Pass large payloads as
attachments[]references (artifact_id, signed URL, checksum, media type). - The Tool Gateway enforces tenant-scoped attachment access at the boundary.
- Attachment hashes are recorded in the
evidence_manifestand the trace.
ToolCallEnvelope
Produced by the Executor for each plan step that calls an adapter; brokered by the Tool Gateway.
{
"envelope_version": "contextos.tool_call.v1",
"tool_call_id": "tool_118",
"run_id": "run_a1b2c3d4e5f60718",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"session_id": "sess_42f1",
"capability_id": "adp_payments.issue_refund",
"args": {
"order_id": "ord_881",
"amount_inr": 4200,
"currency": "INR",
"idempotency_key": "ik_2x9k4j7m1q8w0p3z"
},
"principal_chain": [
{ "kind": "user", "id": "usr_771", "tenant_id": "tenant_acme_prod" },
{ "kind": "agent", "id": "agent:contextos/support-refund@1.2.0", "tenant_id": "tenant_acme_prod" }
],
"approval_mode_requested": "destructive",
"approval_mode_effective": "destructive",
"approval_mode_highest": "destructive",
"policy_decision_id": "pol_9901",
"evidence_refs": [
"kg:order:ord_881#snapshot_kg_2026_05_03_T0930",
"policy:POLICY_RETURNS_V1#R_HIGH_VALUE_REQUIRES_APPROVAL"
],
"idempotency_key": "ik_2x9k4j7m1q8w0p3z",
"auth_ref": "claim_hash:sha256:...",
"metadata": {
"arg_schema_ref": "schema://adp_payments.issue_refund.v3",
"requires_approval_gate": "GATE_FINANCE_APPROVAL",
"protocol": "openapi",
"version": "2026-04-15"
}
}ToolResultEnvelope
Produced by the Tool Gateway after the adapter returns.
{
"envelope_version": "contextos.tool_result.v1",
"tool_call_id": "tool_118",
"run_id": "run_a1b2c3d4e5f60718",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"session_id": "sess_42f1",
"capability_id": "adp_payments.issue_refund",
"status": "completed",
"output": {
"transaction_id": "txn_q9...",
"refund_amount_inr": 4200,
"currency": "INR",
"supplier_rules_ref": "rules:payments:refund:v12"
},
"error": null,
"artifacts": [],
"citations": [
{ "evidence_ref": "tool:adp_payments.issue_refund:tool_118" }
],
"mutations": ["refund:txn_q9"],
"risk_tags": ["destructive"],
"policy_decision_id": "pol_9901",
"latency_ms": 612,
"metadata": {
"approver": "user_finance_lead_77",
"approval_evidence_snapshot_hash": "sha256:b2a1...",
"tool_transcript_id": "tool_tx_118",
"redaction_applied": false,
"retries": 0,
"cost_cents": 0.31
},
}ToolResultEnvelope statuses
| Status | Meaning |
|---|---|
ok | read-only or synchronous operation returned without side effects |
completed | governed operation finished and any declared side effects are represented in mutations[] |
paused | approval, external dependency, or long-running continuation is pending |
blocked | policy or consent blocked execution before the adapter ran |
rejected | gateway rejected malformed, unauthorized, or unsurfaced capability use |
failed | adapter, transport, or runtime execution failed |
error | normalized error result where the caller may inspect error and metadata |
DecisionRecord
The typed outcome the runtime returns after the canonical loop completes.
For the full conceptual contract, lifecycle, validation rules, replay model, and storage requirements, see Decision Record.
{
"record_id": "dr_2026_05_04_a17",
"decision_key": "support.refund.execute",
"decision_version": "1.0.0",
"timestamp": "2026-05-04T09:31:42Z",
"status": "DECIDED",
"actor": { "type": "AGENT", "id": "agt_support" },
"agent_identity": {
"subject": "agent:contextos/support-refund@1.2.0",
"claim_hash": "sha256:...",
"principal_chain": [
{ "kind": "user", "id": "usr_771", "tenant_id": "tenant_acme_prod" },
{ "kind": "agent", "id": "agent:contextos/support-refund@1.2.0", "tenant_id": "tenant_acme_prod" }
]
},
"intent_ref": "support.refund",
"subject_ids": ["customer:cus_77", "order:ord_881"],
"inputs_refs": { "request": "req_9f3a12", "session": "sess_42f1" },
"outputs": {
"refund_amount_inr": 4200,
"currency": "INR",
"transaction_id": "txn_q9..."
},
"evidence_refs": [
"kg:order:ord_881#snapshot_kg_2026_05_03_T0930",
"tool:adp_orders.lookup:tc_117",
"tool:adp_policy.eval:tc_119",
"tool:adp_payments.issue_refund:tc_121"
],
"policy_decisions": [
{ "policy_decision_id": "pol_9900", "rule_ids": ["R_REFUND_REQUIRES_IDV"] },
{ "policy_decision_id": "pol_9901", "rule_ids": ["R_HIGH_VALUE_REQUIRES_APPROVAL"] }
],
"approvals": [
{
"gate_id": "GATE_FINANCE_APPROVAL",
"approver": "user_finance_lead_77",
"approval_mode_effective": "destructive",
"evidence_snapshot_hash": "sha256:b2a1...",
"decided_at": "2026-05-04T09:31:30Z"
}
],
"controls_active": {
"must_refuse": [],
"must_escalate": [],
"approval_gates_active": ["GATE_FINANCE_APPROVAL"],
"redaction_rules_active": []
},
"confidence": 0.95,
"rationale": { "strategy": "policy_match_with_evidence", "alternatives_considered": [] },
"budget_usage": { "tokens": 4720, "tool_calls": 4, "cost_usd_cents": 0.91, "wall_clock_ms": 1840 },
"lineage": { "pack_version": "ctxpack.support@5.2.0", "snapshot_version": "kg_2026_05_03_T0930" },
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}DecisionRecord status values
DECIDED, DEFERRED, REJECTED, ESCALATED, IN_FLIGHT, CLOSED.
Trace context propagation
W3C Trace Context flows across every plane. The Critic, Executor, and Tool Gateway re-emit traceparent on every outbound call. The runtime preserves IDs in the manifests for replay:
{
"trace_context": {
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-b9c7c989f97918e1-01",
"tracestate": "tenant=tenant_acme_prod,ctxpack=ctxpack.support@5.2.0",
"baggage": "session_id=sess_42f1,decision_id=support.refund.execute,run_id=run_a1b2c3d4e5f60718"
}
}Context Pack reference
The pack is loaded by reference. A context_pack_refs[] entry is pack_id@semver, and the runtime refuses unpinned refs.
{ "context_pack_refs": ["ctxpack.support@5.2.0"] }See Context Pack for the full schema.
Compiled output
{
"compiled_prompt": { "system": "...", "developer": "...", "task": "...", "context_blocks": [] },
"manifests": {
"policy_manifest": [{ "bundle_id": "POLICY_RETURNS_V4", "rule_ids": ["R_REFUND_REQUIRES_IDV"] }],
"tool_manifest": [{
"adapter_id": "adp_payments",
"capabilities": ["issue_refund"],
"capability_metadata": {
"issue_refund": {
"kind": "write",
"risk_level": "write_irreversible",
"approval_mode": "destructive",
"source": "adapter_registry"
}
}
}],
"evidence_manifest": [{ "evidence_ref": "kg:order:ord_881#snapshot_kg_2026_05_03_T0930" }]
},
"runtime_controls": {
"must_refuse": [],
"must_escalate": [],
"approval_gates_active": ["GATE_FINANCE_APPROVAL"],
"redaction_rules_active": []
},
"budget_report": {
"tokens_allocated": { "policy": 1800, "tool": 1500, "evidence": 3500, "memory": 1500, "business": 1500, "session": 2200 },
"tokens_used_at_compile": 4720,
"tokens_used_by_bucket": { "policy": 940, "tool": 220, "evidence": 2100, "memory": 460, "business": 510, "session": 490 },
"bucket_truncations": { "evidence": true },
"dropped_block_ids": { "evidence": ["ev_low_priority_7"] },
"warnings": ["evidence bucket exceeded budget; dropped 1 low-priority block"]
},
"context_ledger": {
"pack_ref": "ctxpack.support@5.2.0",
"request_id": "req_9f3a12",
"policy_bundles": ["POLICY_RETURNS_V4"],
"tools": ["adp_payments.issue_refund"],
"evidence_refs": ["kg:order:ord_881#snapshot_kg_2026_05_03_T0930"],
"memory_refs": [],
"budget": { "tokens_used_at_compile": 4720, "truncated_buckets": ["evidence"] },
"compiled_context_hash": "sha256:9f0b..."
}
}The budget_report and context_ledger fields are part of the audit surface. They make replay and operator debugging local: a budget issue names the dropped blocks, and a tool-surfacing question carries capability risk metadata in the manifest itself.
Decision output (snippet)
The Decision Spec the runtime resolves to live alongside the catalog:
{
"decision_id": "support.refund.execute",
"outcome": "approved",
"evidence_refs": ["kg:order:ord_881#snapshot_kg_2026_05_03_T0930", "policy:POLICY_RETURNS_V1#R_HIGH_VALUE_REQUIRES_APPROVAL"]
}