Canonical reference for the DashClaw SDK (v2.11.1). Node.js and Python parity across all core governance features.
npm install dashclaw
import { DashClaw } from 'dashclaw';
const claw = new DashClaw({
baseUrl: process.env.DASHCLAW_BASE_URL,
apiKey: process.env.DASHCLAW_API_KEY,
agentId: 'my-agent'
});// 1. Ask permission — abort on hard block
const decision = await claw.guard({
action_type: 'deploy',
risk_score: 85,
declared_goal: 'Update auth service to v2.1.1'
});
if (decision.decision === 'block') {
throw new Error(`Blocked: ${decision.reason || decision.reasons?.join(', ')}`);
}
// 2. Log intent. The server re-evaluates policy here and is the
// authoritative source for HITL gating.
const { action, action_id } = await claw.createAction({
action_type: 'deploy',
declared_goal: 'Update auth service to v2.1.1'
});
// 3. If the server flagged this, wait for a human operator.
// Pass createAction's action_id — NOT decision.action_id.
if (action?.status === 'pending_approval') {
await claw.waitForApproval(action_id);
}
try {
// 4. Log evidence
await claw.recordAssumption({
action_id,
assumption: 'Tests passed'
});
// ... deploy ...
// 5. Record outcome
await claw.updateOutcome(action_id, { status: 'completed' });
} catch (err) {
await claw.updateOutcome(action_id, { status: 'failed', error_message: err.message });
}@dashclaw/mcp-server exposes DashClaw governance over Model Context Protocol. Any MCP-compatible client gets 8 governance tools and 4 read-only resources.
| Tool | Description | Key Inputs |
|---|---|---|
| dashclaw_guard | Evaluate policies before risky actions | action_type, declared_goal, risk_score |
| dashclaw_record | Log action to audit trail | action_type, declared_goal, status |
| dashclaw_invoke | Execute governed capability | capability_id, declared_goal, payload |
| dashclaw_capabilities_list | Discover available APIs | category, risk_level, search |
| dashclaw_policies_list | List active policies | agent_id |
| dashclaw_wait_for_approval | Wait for human decision | action_id, timeout_seconds |
| dashclaw_session_start | Register agent session | agent_id, workspace |
| dashclaw_session_end | Close session | session_id, status, summary |
| URI | Description |
|---|---|
| dashclaw://policies | Active policy set |
| dashclaw://capabilities | Available capabilities and health |
| dashclaw://agent/{agent_id}/history | Recent action history (last 50) |
| dashclaw://status | Instance health + operational metrics |
Config resolution: CLI args > env vars > defaults. Three config values: url (DASHCLAW_URL, default localhost:3000), apiKey (DASHCLAW_API_KEY), agentId (DASHCLAW_AGENT_ID).
{
"mcpServers": {
"dashclaw": {
"command": "npx",
"args": ["@dashclaw/mcp-server"],
"env": {
"DASHCLAW_URL": "https://your-instance.vercel.app",
"DASHCLAW_API_KEY": "oc_live_..."
}
}
}
}mcp_servers=[{
"type": "url",
"url": "https://your-instance.vercel.app/api/mcp",
"headers": {"x-api-key": "oc_live_..."},
"name": "dashclaw"
}]@dashclaw/cli handles terminal approvals and self-host diagnostics. npm run doctor runs the same engine locally with filesystem-level fix powers.
Diagnoses database, configuration, auth, deployment, SDK reachability, governance staleness, and livingcode shape drift — auto-fixing safe issues. Invokes GET /api/doctor and POST /api/doctor/fix. For operators, npm run doctor on the host adds .env writes, migrations, and default-policy seeding (backs up .env before any write).
npm install -g @dashclaw/cli dashclaw doctor # rich terminal output, auto-fix safe issues dashclaw doctor --json # CI / scripts dashclaw doctor --no-fix # diagnose only dashclaw doctor --category database,config # Config resolution: env vars → ~/.dashclaw/config.json (600) → interactive prompt dashclaw logout # remove saved config # Self-host operator (filesystem-level fixes) npm run doctor
@dashclaw/openclaw-plugin wires governance into the OpenClaw agent framework. Intercepts PreToolUse / PostToolUse lifecycle hooks, calls guard / record / wait-for-approval automatically, and ships a HOOK.md pack the openclaw CLI installs. Tool classification vocabulary aligns with DashClaw guard action types.
@dashclaw/governance is an Anthropic Claude skill that teaches governed agents how to use the MCP tools correctly — risk thresholds, decision handling, recording rules, session lifecycle. Pairs with @dashclaw/mcp-server for Managed Agents. Download the zip from your instance at /downloads/dashclaw-governance.zip.
const claw = new DashClaw({ baseUrl, apiKey, agentId });| Parameter | Type | Required | Description |
|---|---|---|---|
| baseUrl / base_url | string | Yes | Dashboard URL |
| apiKey / api_key | string | Yes | API Key |
| agentId / agent_id | string | Yes | Unique Agent ID |
Evaluate guard policies for a proposed action. Call this before risky operations. The guard response includes a `learning` field with historical performance context when available (recent scores, drift status, learned patterns, feedback summary).
| Parameter | Type | Required | Description |
|---|---|---|---|
| action_type | string | Yes | Proposed action type |
| risk_score | number | No | 0-100 |
Returns: Promise<{ decision: string, reasons: string[], risk_score: number, agent_risk_score: number | null }>
const result = await claw.guard({ action_type: 'deploy', risk_score: 85 });Create a governance action record. The server re-evaluates policy at this point, so this call is the authoritative source for HITL gating: if policy requires human review, the response is HTTP 202 with action.status='pending_approval'. Always check action.status before assuming the action is clear to execute.
Returns: Promise<{ action: { action_id, status, ... }, action_id, decision, security }>
const { action, action_id } = await claw.createAction({ action_type: 'deploy' });
if (action?.status === 'pending_approval') {
// gate execution on waitForApproval — see the method below
}Wait for a human operator to approve or deny an action. Opens an SSE stream on /api/stream and falls back to polling /api/actions/:id every 5 seconds. Resolves when action.approved_by is set; throws ApprovalDeniedError when the operator denies; throws on timeout. IMPORTANT: pass the action_id returned by createAction() — NOT the action_id returned by guard(). They refer to different database tables and waiting on a guard decision ID will never resolve. Approvals can be resolved from the dashboard (/approvals), the CLI (dashclaw approve <id>), the mobile PWA (/approve), or — if the instance has Telegram configured (TELEGRAM_BOT_TOKEN) — via an inline Approve/Reject button pushed to the admin Telegram chat. All four surfaces call the same /api/approvals/:id endpoint, so waitForApproval unblocks the agent within ~1 second regardless of which surface was used.
// Correct — wait on createAction's action_id
const { action, action_id } = await claw.createAction({ action_type: 'deploy' });
if (action?.status === 'pending_approval') {
await claw.waitForApproval(action_id, { timeout: 600_000 });
}Log final results. Accepts status, output_summary, error_message, duration_ms, tokens_in, tokens_out, model, cost_estimate. When tokens + model are supplied without cost_estimate, the server derives cost from the pricing table.
await claw.updateOutcome(action_id, {
status: 'completed',
tokens_in: result.usage.input_tokens,
tokens_out: result.usage.output_tokens,
model: result.model,
});Track agent beliefs.
await claw.recordAssumption({ action_id, assumption: '...' });Get current risk signals across all agents.
Returns: Promise<{ signals: Object[] }>
const { signals } = await claw.getSignals();Report agent presence and health to the control plane. Call periodically to indicate the agent is alive.
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | Agent status — 'online', 'busy', 'idle'. Defaults to 'online' |
| metadata | object | No | Arbitrary metadata to include with the heartbeat |
await claw.heartbeat('online', { cycle: 42, uptime_ms: 360000 });Report active provider connections and their status. Appears in the agent's Fleet profile.
| Parameter | Type | Required | Description |
|---|---|---|---|
| connections | Array<Object> | Yes | List of { name, type, status } connection objects |
await claw.reportConnections([
{ name: 'OpenAI', type: 'llm', status: 'connected' },
{ name: 'Postgres', type: 'database', status: 'connected' },
]);Register an unresolved dependency for a decision. Open loops track work that must be completed before the decision is fully resolved.
| Parameter | Type | Required | Description |
|---|---|---|---|
| action_id | string | Yes | Associated action |
| loop_type | string | Yes | The category of the loop |
| description | string | Yes | What needs to be resolved |
await claw.registerOpenLoop(action_id, 'validation', 'Waiting for PR review');
Resolve a pending loop.
await claw.resolveOpenLoop(loop_id, 'completed', 'Approved');
Record what the agent believed to be true when making a decision.
await claw.recordAssumption({ action_id, assumption: 'User is authenticated' });Compute learning velocity (rate of score improvement) for agents.
Returns: Promise<{ velocity: Array<Object> }>
const { velocity } = await claw.getLearningVelocity();Compute learning curves per action type to measure efficiency gains.
const curves = await claw.getLearningCurves();
Fetch consolidated lessons from scored outcomes — what DashClaw has learned about this agent's performance patterns.
| Parameter | Type | Required | Description |
|---|---|---|---|
| actionType | string | No | Filter by action type |
| limit | number | No | Max lessons to return (default 10) |
Returns: Promise<{ lessons: Object[], drift_warnings: Object[], agent_id: string }>
const { lessons, drift_warnings } = await claw.getLessons({ actionType: 'deploy' });
lessons.forEach(l => console.log(l.guidance));Fetch rendered prompt from DashClaw.
const { rendered } = await claw.renderPrompt({
template_id: 'marketing',
variables: { company: 'Apple' }
});Create a reusable scorer definition for automated evaluation.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Scorer name |
| scorer_type | string | Yes | Type (llm_judge, regex, range) |
| config | object | No | Scorer configuration |
await claw.createScorer('toxicity', 'regex', { pattern: 'bad-word' });Define weighted quality scoring profiles across multiple scorers.
await claw.createScoringProfile({
name: 'prod-quality',
dimensions: [{ scorer: 'toxicity', weight: 0.5 }]
});Send a point-to-point message or broadcast to all agents in the organization.
| Parameter | Type | Required | Description |
|---|---|---|---|
| to | string | No | Target agent ID (omit for broadcast) |
| body | string | Yes | Message content |
| type | string | No | action|info|lesson|question |
| urgent | boolean | No | Mark as high priority |
await claw.sendMessage({
to: 'scout-agent-01',
body: 'I have finished indexing the repository. You can start the analysis.',
type: 'status'
});Retrieve messages from the agent inbox with optional filtering.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | string | No | Filter by message type |
| unread | boolean | No | Only return unread messages |
| limit | number | No | Max messages to return |
Returns: Promise<{ messages, total, unread_count }>
const { messages } = await claw.getInbox({ unread: true, limit: 10 });Create a session handoff document to persist state between agent sessions or transfer context to another agent.
await claw.createHandoff({
summary: 'Completed initial data collection from Jira.',
key_decisions: ['Prioritize high-severity bugs', 'Ignore closed tickets'],
open_tasks: ['Run security scan on src/', 'Draft fix for #123'],
next_priorities: ['Security audit']
});Retrieve the most recent handoff for the current agent.
Returns: Promise<Object|null>
const handoff = await claw.getLatestHandoff();
Scan untrusted input for potential prompt injection or jailbreak attempts.
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | string | Yes | Untrusted input to scan |
Returns: Promise<{ clean: boolean, risk_level: string, recommendation: string }>
const result = await claw.scanPromptInjection(userInput);
if (!result.clean) {
console.warn('Injection risk:', result.risk_level);
}Submit feedback for a specific agent action. Used for human evaluation of agent performance.
| Parameter | Type | Required | Description |
|---|---|---|---|
| action_id | string | Yes | Target action ID |
| rating | number | Yes | 1-5 star rating |
| comment | string | No | Textual feedback |
| category | string | No | Grouping tag |
await claw.submitFeedback({
action_id: 'act_4b2s8...',
rating: 4,
comment: 'Action was safe and effective but took longer than expected.',
category: 'performance_review'
});Create a new context thread to track a multi-step reasoning chain or investigation.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Thread name |
| summary | string | No | Initial thread summary |
Returns: Promise<{ thread, thread_id }>
const { thread } = await claw.createThread({ name: 'Deploy analysis', summary: 'Evaluating safety' });Append an observation, conclusion, or decision to an existing context thread.
| Parameter | Type | Required | Description |
|---|---|---|---|
| threadId | string | Yes | Thread ID to append to |
| content | string | Yes | Entry content |
| entryType | string | Yes | 'observation' | 'conclusion' | 'decision' |
await claw.addThreadEntry('ct_abc123', 'Staging checks passed', 'observation');Close a context thread, optionally providing a final summary.
| Parameter | Type | Required | Description |
|---|---|---|---|
| threadId | string | Yes | Thread ID to close |
| summary | string | No | Final summary of the thread |
await claw.closeThread('ct_abc123', 'Deploy approved after staging check');Bulk-sync agent state including decisions, lessons, goals, context, relationships, memory, and preferences in a single call.
| Parameter | Type | Required | Description |
|---|---|---|---|
| state | object | Yes | State object with keys: decisions, lessons, goals, context, relationships, memory, preferences |
await claw.syncState({ decisions: [...], lessons: [...], goals: [...] });Enroll agents via public-key pairing and manage approved identities. Pairing requests are created by agents; approval is an admin action. Once approved, the agent's public key is registered as a trusted identity for signature verification.
Create an agent pairing request. The agent submits its public key and waits for operator approval.
| Parameter | Type | Required | Description |
|---|---|---|---|
| public_key | string | Yes | PEM-encoded RSA public key |
| algorithm | string | No | Key algorithm. Default: RSASSA-PKCS1-v1_5 |
| agent_name | string | No | Human-readable label for the agent |
Returns: { pairing: { id, status, agent_name, created_at } }
// Node SDK (v1 legacy)
import { DashClaw } from 'dashclaw/legacy';
const claw = new DashClaw({ baseUrl, apiKey, agentId });
const { pairing } = await claw.createPairing(publicKeyPem, 'RSASSA-PKCS1-v1_5', 'my-agent');
console.log(pairing.id); // pair_...List all pairing requests for the organization. Admin API key required.
Returns: { pairings: Array<{ id, status, agent_name, created_at, approved_at }> }
const res = await fetch('/api/pairings', {
headers: { 'x-api-key': adminApiKey }
});
const { pairings } = await res.json();Get a specific pairing request by ID. Used by agents to poll for approval status.
Returns: { pairing: { id, status, agent_name, created_at, approved_at } }
// Node SDK (v1 legacy) const status = await claw.getPairing(pairingId); console.log(status.pairing.status); // pending | approved | expired
Approve a pending pairing request. Admin API key required. On approval, the agent's public key is registered as a trusted identity.
Returns: { pairing: { id, status, approved_at } }
const res = await fetch(`/api/pairings/${pairingId}/approve`, {
method: 'POST',
headers: { 'x-api-key': adminApiKey }
});Directly register an agent's public key as a trusted identity. Admin API key required. Bypasses the pairing flow.
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | Unique agent identifier |
| public_key | string | Yes | PEM-encoded RSA public key |
| algorithm | string | No | Key algorithm. Default: RSASSA-PKCS1-v1_5 |
Returns: { identity: { agent_id, algorithm, created_at } }
// Node SDK (v1 legacy)
await claw.registerIdentity('agent-007', publicKeyPem, 'RSASSA-PKCS1-v1_5');List all registered agent identities for the organization. Admin API key required.
Returns: { identities: Array<{ agent_id, algorithm, created_at }> }
// Node SDK (v1 legacy)
const { identities } = await claw.getIdentities();Revoke a registered agent identity. Admin API key required. The agent's public key is removed and signature verification will fail for future actions.
Returns: { success: true }
const res = await fetch(`/api/identities/${agentId}`, {
method: 'DELETE',
headers: { 'x-api-key': adminApiKey }
});Governance packaging: workflow templates, model strategies, knowledge collections, a capability registry, and a read-only execution graph on actions. Every surface here has a canonical SDK wrapper method in the v2 Node SDK (see sdk/dashclaw.js, 80 methods total). The HTTP examples below are shown first because they're language-agnostic; the equivalent SDK calls (claw.listWorkflowTemplates, claw.execution.capabilities.invoke, etc.) are in sdk/README.md → Execution Studio. Full OpenAPI definitions are at docs/openapi/critical-stable.openapi.json.
Read-only execution graph (nodes + edges) for any action. Reuses the existing trace data plus correlated assumptions and open loops — zero schema change. Powers the Graph tab on decision replay.
Returns: { rootActionId, nodes: Array<{ id, type, status, riskScore, ... }>, edges: Array<{ source, target, type, label }> }
const res = await fetch(`${baseUrl}/api/actions/${actionId}/graph`, {
headers: { 'x-api-key': apiKey }
});
const { rootActionId, nodes, edges } = await res.json();
// node ids: action:<id>, assumption:<id>, loop:<id>
// edge types: parent_child | related | assumption_of | loop_fromPackage a repeatable operational pattern as a reusable, versioned asset linking policies, prompts, knowledge, capabilities, and a model strategy.
List all workflow templates for the current org. Supports ?status=draft|active|archived, ?limit, ?offset.
const { templates } = await fetch(`${baseUrl}/api/workflows/templates`, {
headers: { 'x-api-key': apiKey }
}).then(r => r.json());Create a workflow template. Slug auto-generated from name if omitted. Starts as v1, status=draft. Body fields: name (required), description, objective, steps, linked_prompt_template_ids, linked_policy_ids, linked_knowledge_collection_ids, linked_capability_ids, linked_capability_tags, model_strategy_id, status.
await fetch(`${baseUrl}/api/workflows/templates`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Release Hotfix',
description: 'Ship urgent production patches safely',
objective: 'Deploy with full policy + approval coverage',
linked_policy_ids: ['pol_prod_deploy'],
linked_capability_tags: ['deploy'],
model_strategy_id: 'mst_balanced_default'
})
});Fetch or partially update a template. PATCH bumps version by 1 when the steps array changes; all linked arrays and metadata can be updated in the same call.
await fetch(`${baseUrl}/api/workflows/templates/${templateId}`, {
method: 'PATCH',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
steps: [{ id: 'plan' }, { id: 'test' }, { id: 'deploy' }]
})
});Clone a template as a new draft (version resets to 1, status='draft'). Accepts optional name and slug overrides in the body.
const { template } = await fetch(
`${baseUrl}/api/workflows/templates/${templateId}/duplicate`,
{ method: 'POST', headers: { 'x-api-key': apiKey } }
).then(r => r.json());Launch a template. Creates a new row in action_records with trigger='workflow:<templateId>' and reasoning='WORKFLOW_LAUNCH_META=<json>' carrying the full template context. If the template links a model_strategy_id, the resolved config is fetched and snapshotted onto the launched action and the template. No schema columns were added to action_records — Phase 1 piggybacks on existing trace primitives.
Returns: { launch: { action_id, template_id, template_version, launched_at, resolved_strategy } }
const { launch } = await fetch(
`${baseUrl}/api/workflows/templates/${templateId}/launch`,
{
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ agent_id: 'deploy-bot' })
}
).then(r => r.json());
// The launched action is immediately traceable in decision replay
console.log(`${baseUrl}/decisions/${launch.action_id}`);List past workflow executions for a template. Each run is a parent action_record with step counts from workflow_step_results. Supports status, agent_id, limit, and offset query params.
Returns: { template_id, runs: [{ run_action_id, template_id, status, agent_id, declared_goal, duration_ms, started_at, finished_at, step_count, steps_completed, steps_failed }], total }
const runs = await fetch(
`${baseUrl}/api/workflows/templates/${templateId}/runs?limit=10`,
{ headers: { 'x-api-key': apiKey } }
).then(r => r.json());
runs.runs.forEach(r =>
console.log(`${r.status} — ${r.steps_completed}/${r.step_count} steps — ${r.duration_ms}ms`)
);Fetch full run detail including all step results with complete input/output JSON. Powers the run detail page. Each step includes the resolved input after variable interpolation and the full output (no truncation).
Returns: { run_action_id, template_id, template_name, status, agent_id, declared_goal, duration_ms, started_at, finished_at, error_message, steps: [{ step_id, step_index, step_type, step_name, status, input, output, error_message, retry_count, duration_ms }] }
const run = await fetch(
`${baseUrl}/api/workflows/templates/${templateId}/runs/${runActionId}`,
{ headers: { 'x-api-key': apiKey } }
).then(r => r.json());
const failed = run.steps.filter(s => s.status === 'failed');
failed.forEach(s =>
console.log(`Step ${s.step_name} failed: ${s.error_message}`)
);Reusable provider/model strategy records (primary + fallback chain, cost/latency sensitivity, budget cap). Linked from workflow templates and snapshotted at launch.
List all strategies or create a new one. Config is validated server-side: primary.provider and primary.model are required; costSensitivity must be one of low | balanced | high-quality; latencySensitivity must be low | medium | high; maxBudgetUsd must be a number; maxRetries must be an integer; fallback, allowedProviders, and disallowedProviders must be arrays if provided.
await fetch(`${baseUrl}/api/model-strategies`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Balanced Default',
description: 'GPT-4.1 primary, Claude Sonnet 4 fallback',
config: {
primary: { provider: 'openai', model: 'gpt-4.1' },
fallback: [{ provider: 'anthropic', model: 'claude-sonnet-4' }],
costSensitivity: 'balanced',
latencySensitivity: 'medium',
maxBudgetUsd: 0.5,
maxRetries: 2,
allowedProviders: ['openai', 'anthropic']
}
})
});Fetch, update, or delete a strategy. PATCH merges config patches over the existing config (primary fields preserved unless overridden). DELETE nulls out the soft reference on any linked workflow_templates rather than orphaning them.
await fetch(`${baseUrl}/api/model-strategies/${strategyId}`, {
method: 'PATCH',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ config: { maxBudgetUsd: 1.0 } })
});Execute a chat completion using this strategy. Resolves BYOK provider credentials from org settings, walks the fallback chain (primary provider first, then each fallback), enforces maxBudgetUsd, and returns a normalized response. Supports task_mode to override primary with the corresponding taskModes entry. Providers supported: openai, anthropic, groq, together, perplexity. Returns 502 with provider_errors array when all providers fail.
| Parameter | Type | Required | Description |
|---|---|---|---|
| messages | Array<{ role, content }> | Yes | Chat messages (system, user, assistant) |
| max_tokens | number | No | Max output tokens (default 1024) |
| temperature | number | No | Sampling temperature (default 0.7) |
| task_mode | string | No | Override primary with taskModes[mode] if defined in strategy config |
Returns: { content, provider, model, usage: { input_tokens, output_tokens }, cost_usd, fallback_used, attempts, strategy_id, strategy_name }
const result = await claw.completeWithStrategy(strategyId, [
{ role: 'user', content: 'Summarize the deploy plan' }
], { max_tokens: 512, task_mode: 'reasoning' });
console.log(result.content); // LLM response
console.log(result.provider); // which provider handled it
console.log(result.cost_usd); // estimated cost
console.log(result.fallback_used); // true if primary failedLightweight metadata layer for knowledge sources that workflows and agents can bind to. No embedding or retrieval in Phase 1 — metadata + tags only.
List collections (filter by ?source_type) or create a new one. source_type must be one of files | urls | external | notes. New collections start with ingestion_status='empty' and doc_count=0.
await fetch(`${baseUrl}/api/knowledge/collections`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Runbook Library',
description: 'Incident response runbooks',
source_type: 'files',
tags: ['ops', 'oncall']
})
});Fetch or update a collection's metadata (name, description, source_type, tags, ingestion_status).
const { collection } = await fetch(
`${baseUrl}/api/knowledge/collections/${collectionId}`,
{ headers: { 'x-api-key': apiKey } }
).then(r => r.json());List or add items in a collection. Adding an item increments the parent collection's doc_count atomically and transitions ingestion_status from 'empty' to 'pending' on the first item. Items carry source_uri (required), title, mime_type, status, and a metadata object.
await fetch(
`${baseUrl}/api/knowledge/collections/${collectionId}/items`,
{
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
source_uri: 'https://docs.example.com/runbook.md',
title: 'Deploy runbook',
mime_type: 'text/markdown'
})
}
);Caller-invoked ingestion: fetches source_uri content for each pending item, chunks text (~500 tokens with overlap), generates embeddings via BYOK OpenAI key (text-embedding-3-small, 1536 dims), and stores in the knowledge_chunks table (pgvector). Updates item status (pending → indexed/failed) and collection ingestion_status. Bounded to 50 items per call — designed for Vercel free tier (no cron required).
Returns: { sync: { ingested, failed, chunks_created, errors } }
// SDK
const { sync } = await claw.syncKnowledgeCollection(collectionId);
console.log(sync.ingested, sync.chunks_created);Semantic search over chunked + embedded content. Embeds the query via BYOK OpenAI key, then uses pgvector cosine distance to find the most relevant chunks. Returns top-k results with similarity scores, chunk content, and source item metadata.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Natural language search query |
| limit | number | No | Max results (default 5, max 20) |
Returns: { query, collection_id, results: Array<{ chunk_id, item_id, content, score, position, token_count, title, source_uri }>, count }
const { results } = await claw.searchKnowledgeCollection(
collectionId,
'How do I roll back a deploy?',
{ limit: 5 }
);
results.forEach(r => console.log(`${(r.score * 100).toFixed(1)}%: ${r.content.slice(0, 80)}`));Governed registry of callable capabilities with risk, approval, health, and (future) pricing metadata. Workflow templates can reference capabilities by id or by tag.
Search or register a capability. GET supports combinable filters: ?category, ?risk_level (low|medium|high|critical), ?search (ILIKE on name/description/tags). source_type must be one of internal_sdk | http_api | webhook | human_approval | external_marketplace. (org_id, slug) is unique — POST returns 409 on duplicate slug.
await fetch(`${baseUrl}/api/capabilities`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Send Slack Message',
description: 'Posts to a configured Slack channel',
category: 'messaging',
source_type: 'http_api',
auth_type: 'oauth',
risk_level: 'medium',
requires_approval: false,
tags: ['notify', 'slack'],
health_status: 'healthy',
docs_url: 'https://docs.example.com/slack'
})
});Fetch or update a capability. PATCH validates risk_level and source_type enums on change.
await fetch(`${baseUrl}/api/capabilities/${capabilityId}`, {
method: 'PATCH',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ health_status: 'degraded' })
});Governed capability invocation with retry policies, circuit breaker, and health tracking. Capabilities with retry_policy retry transient failures automatically. Capabilities with circuit_breaker auto-block after consecutive failures (reset via test route).
Execute a governed capability invocation. Evaluates guard policies, scans for sensitive data, enforces quota, runs the HTTP call with optional retry, and records a full action audit trail. Returns retry_metadata when retry_policy is configured. Returns 503 circuit_breaker_open when the circuit breaker is tripped.
const res = await fetch(`${baseUrl}/api/capabilities/${capabilityId}/invoke`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'What is x402?' })
});
const data = await res.json();
// data.success, data.action_id, data.result, data.elapsed_ms, data.governed
// data.retry_metadata (when retry_policy configured): { total_attempts, retried, attempts }Run a non-production validation call. Bypasses guard policies and circuit breaker. Updates capability health_status and certification_status based on the result. Use this to certify a capability or reset an open circuit breaker.
const res = await fetch(`${baseUrl}/api/capabilities/${capabilityId}/test`, {
method: 'POST',
headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'test input' })
});
const data = await res.json();
// data.tested, data.health_status, data.certification_statusFetch derived health summary including success rates (1d/7d), p95 latency, certification status, recent errors, and stale check. Computed from action_records over the past 7 days.
const res = await fetch(`${baseUrl}/api/capabilities/${capabilityId}/health`, {
headers: { 'x-api-key': apiKey }
});
const health = await res.json();
// health.status (healthy|degraded|failing|untested)
// health.certification_status (certified|stale|failed|uncertified)
// health.success_rate_1d, health.success_rate_7d, health.p95_latency_msFetch invocation and test event history for a capability. Filter by action_type (capability_invoke, capability_test) and status (completed, failed, running, pending_approval). Supports limit and offset pagination.
const res = await fetch(`${baseUrl}/api/capabilities/${capabilityId}/history?status=failed&limit=10`, {
headers: { 'x-api-key': apiKey }
});
const history = await res.json();
// history.events[].action_id, action_type, status, error_message, duration_msFetch aggregated governance analytics for the organization over a rolling window. Includes action counts, guard decision totals, signal summaries, and assumption stats. Supports ?days (1–365, default 30).
| Parameter | Type | Required | Description |
|---|---|---|---|
| days | number | No | Rolling window in days (1–365). Defaults to 30. |
Returns: { actions_total, actions_by_status, guard_decisions_total, guard_decisions_by_outcome, signals_total, assumptions_total }
const res = await fetch(`${baseUrl}/api/analytics?days=7`, {
headers: { 'x-api-key': apiKey }
});
const data = await res.json();
// data.actions_total, data.guard_decisions_total, data.signals_totalList guard evaluation records for the organization. Returns paginated decisions with matched policies and declared goal context. Supports filtering by ?decision (allow|block|flag), ?agent_id, ?limit (max 200), and ?offset.
| Parameter | Type | Required | Description |
|---|---|---|---|
| decision | string | No | Filter by outcome: allow | block | flag |
| agent_id | string | No | Filter to a specific agent |
| limit | number | No | Page size (max 200, default 50) |
| offset | number | No | Pagination offset (default 0) |
Returns: { decisions: Array<{ id, agent_id, action_type, decision, matched_policies, declared_goal, agent_name, created_at }>, total, stats }
const res = await fetch(`${baseUrl}/api/guard/decisions?decision=block&limit=25`, {
headers: { 'x-api-key': apiKey }
});
const { decisions, total, stats } = await res.json();
// decisions[].decision, decisions[].matched_policies, decisions[].declared_goalFetch the full governance profile for a specific agent. Includes identity, presence (heartbeat state), trust posture, computed risk signals, and assumptions summary. Returns 404 if the agent has not been seen by the instance.
| Parameter | Type | Required | Description |
|---|---|---|---|
| agentId | string | Yes | The agent identifier (path parameter) |
Returns: { agent: { agent_id, agent_name, action_count, last_active, presence: { status, last_heartbeat_at, current_task_id } }, trust, signals, assumptions_summary }
const res = await fetch(`${baseUrl}/api/agents/my-agent/profile`, {
headers: { 'x-api-key': apiKey }
});
const { agent, trust, signals, assumptions_summary } = await res.json();
// agent.presence.status, trust.risk_score, signals, assumptions_summary{ message: "Validation failed", status: 400 }