Skip to main content
What this is for: every JSON-RPC method the daemon exposes — what to send, what comes back, and which scope you need. Who it’s for: developers building CLIs, dashboards, or external integrations against the Comis gateway. Complete reference for all JSON-RPC methods available over the Comis gateway WebSocket and HTTP transports. The gateway exposes 167 methods across 39 namespaces covering agent execution, memory, configuration, sessions, scheduling, browser automation, context engine, workspace management, media processing, image generation, text-to-speech, link enrichment, cross-channel messaging, sub-agent lifecycle, platform actions, notifications, environment secrets, and administrative operations. Methods are accessed via the JSON-RPC 2.0 protocol over the WebSocket endpoint at /ws or the HTTP endpoint at POST /rpc. Method count is sourced from packages/core/src/api-contracts/ contract files (167 unique method strings across 39 namespaces). The 29 handler-factory modules in packages/daemon/src/api/rpc-dispatch.ts implement these contracts. Some older handler files may use additional direct-keyed methods not yet covered by the contracts layer; 167 represents the formally declared public API surface.

Session-creation walkthrough

The most common end-to-end flow: open a connection, ping for liveness, kick off an agent execution, and check the resulting session. Every step is one JSON-RPC call.
1

Connect with a bearer token

Open the WebSocket and authenticate. If the token is invalid, the server closes with code 4001.
wscat -c ws://localhost:4766/ws -H "Authorization: Bearer $COMIS_GATEWAY_TOKEN"
2

Verify liveness

system.ping is the cheapest method and a good way to validate auth + transport before sending real work.
{"jsonrpc":"2.0","method":"system.ping","id":1}
Response: {"jsonrpc":"2.0","result":{"pong":true,"ts":1773313498000},"id":1}
3

Execute an agent turn

agent.execute runs one full turn through the agent pipeline. The first call to a fresh sessionKey implicitly creates the session.
{
  "jsonrpc": "2.0",
  "method": "agent.execute",
  "params": {
    "agentId": "default",
    "message": "Summarize today's commits in two bullet points.",
    "sessionKey": {
      "tenantId": "default",
      "userId": "alice",
      "channelId": "cli"
    }
  },
  "id": 2
}
Response carries response, tokensUsed, and finishReason.
4

Inspect or list the session

session.list enumerates active sessions; session.history reads the full message log for one session.
{"jsonrpc":"2.0","method":"session.list","id":3}
5

Clean up when done

Use session.delete (admin) to remove a session. The session entry plus its memory entries are dropped.
{
  "jsonrpc": "2.0",
  "method": "session.delete",
  "params": { "key": "default:alice:cli" },
  "id": 4
}
That same pattern works whether you call over WebSocket or POST /rpc. For streaming token deltas use the SSE endpoint GET /api/chat/stream documented in HTTP Gateway.

Scopes

Every JSON-RPC method requires a specific scope. Tokens are configured in gateway.tokens[] with a scopes array.
ScopeAccess LevelDescription
rpcStandardClient operations: agent execution, memory search, cron management, browser, skills, graphs
adminAdministrativeConfig, agent management, memory management, observability, tokens, channels
*WildcardAccess to all methods (both rpc and admin)
A token with scopes: ["rpc"] can only call rpc-scoped methods. A token with scopes: ["*"] has access to all methods. Calling a method without sufficient scope returns error code -32603 with message "Insufficient scope: requires 'admin'".

Request Format

All methods use JSON-RPC 2.0 format. See WebSocket Protocol for transport details.
{
  "jsonrpc": "2.0",
  "method": "namespace.method",
  "params": { "key": "value" },
  "id": 1
}
The params object is optional and defaults to {} when omitted. The id field correlates requests with responses.

Methods by Namespace

Health check and connectivity testing.
MethodScopeDescription
system.pingrpcReturns a pong response with server timestamp

system.ping

PropertyValue
Scoperpc
ParametersNone
Returns{ pong: true, ts: number }
{
  "jsonrpc": "2.0",
  "method": "system.ping",
  "id": 1
}
Agent execution for processing user messages through the LLM pipeline, cache statistics inspection, and per-operation model resolution introspection.
MethodScopeDescription
agent.cacheStatsadminGet prompt cache statistics for an agent
agent.executerpcExecute an agent turn (non-streaming)
agent.streamrpcExecute an agent turn with streaming token deltas
agent.getOperationModelsadminShow how each agent operation resolves to a concrete model

agent.cacheStats

PropertyValue
Scopeadmin
Parameters{ agentId?: string }
ReturnsCache statistics object with hit/miss rates and cache sizes
{
  "jsonrpc": "2.0",
  "method": "agent.cacheStats",
  "params": { "agentId": "default" },
  "id": 1
}

agent.execute

PropertyValue
Scoperpc
Parameters{ message: string, agentId?: string, sessionKey?: object, scopes?: string[] }
Returns{ response: string, tokensUsed: { input, output, total }, finishReason: string }
{
  "jsonrpc": "2.0",
  "method": "agent.execute",
  "params": {
    "message": "Hello, how are you?",
    "agentId": "default"
  },
  "id": 1
}

agent.stream

Same parameters as agent.execute. Token-delta streaming over JSON-RPC is not currently implemented — the gateway logs a warning and falls back to a non-streaming response. For real-time streaming use the SSE endpoint GET /api/chat/stream documented in HTTP Gateway.

agent.getOperationModels

Inspect how each agent operation (chat, classifier, summarizer, etc.) resolves to a concrete provider+model. Returns the agent’s primary model and provider family, whether tiered model routing is active, and a per-operation breakdown including the resolved model, source (config or default), per-operation timeout, cross-provider flag, and whether the API key for the resolved provider is configured.
PropertyValue
Scopeadmin
Parameters{ agentId: string }
Returns{ agentId, primaryModel, providerFamily, tieringActive, operations: Array<{ operationType, model, provider, source, tieringActive, timeoutMs, crossProvider, apiKeyConfigured }> }
Configuration reading, writing, schema inspection, history, and rollback. Read-only methods and mutations for runtime config management.
MethodScopeDescription
config.applyadminApply full config object
config.diffadminGet unified diff between config versions
config.gcadminRun config garbage collection
config.getadminRead a config section (core method)
config.historyadminGet git-backed config change history
config.patchadminPatch config value with persistence
config.readadminRead config with section filtering and secret redaction
config.rollbackadminRollback config to a previous version
config.schemaadminGet JSON Schema for config sections
config.setadminWrite a config value (core method)

config.read

Read the current configuration, optionally filtered to a specific section. Secret values are automatically redacted in the response.
PropertyValue
Scopeadmin
Parameters{ section?: string }
ReturnsSection object (if section specified) or { config: {...}, sections: string[] }
{
  "jsonrpc": "2.0",
  "method": "config.read",
  "params": { "section": "gateway" },
  "id": 1
}

config.schema

PropertyValue
Scopeadmin
Parameters{ section?: string }
Returns{ schema: object, sections: string[], section?: string }

config.patch

PropertyValue
Scopeadmin
ParametersPatch object (deep-merged with current config)
ReturnsUpdated config acknowledgment

config.apply

PropertyValue
Scopeadmin
ParametersFull config object to apply
ReturnsApplied config acknowledgment

config.diff

PropertyValue
Scopeadmin
Parameters{ sha?: string } — compare against a specific config version
Returns{ diff: string } — unified diff of config changes

config.gc

PropertyValue
Scopeadmin
ParametersNone
ReturnsGarbage collection result

config.history

PropertyValue
Scopeadmin
Parameters{ limit?: number }
Returns{ entries: object[] } — git-backed config change history
{
  "jsonrpc": "2.0",
  "method": "config.history",
  "params": { "limit": 5 },
  "id": 1
}

config.rollback

PropertyValue
Scopeadmin
Parameters{ sha: string } — the version SHA to rollback to
ReturnsRollback confirmation

config.get

Read a raw config section. Unlike config.read, this is a core gateway method that returns the section without secret redaction. Use config.read from application code; config.get exists for internal gateway wiring.
PropertyValue
Scopeadmin
Parameters{ section?: string }
ReturnsRecord<string, unknown> — the requested section, or the full sanitized config if no section is given

config.set

Write a single config value. This is a core gateway method that forwards to config.patch internally. For most use cases, config.patch gives you more control over the merge behavior.
PropertyValue
Scopeadmin
Parameters{ section: string, key: string, value: unknown }
Returns{ ok: true, previous?: unknown }
{
  "jsonrpc": "2.0",
  "method": "config.set",
  "params": {
    "section": "gateway",
    "key": "port",
    "value": 4767
  },
  "id": 1
}
Gateway server status, process information, and restart.
MethodScopeDescription
gateway.restartadminRestart the gateway server
gateway.statusadminProcess info: PID, uptime, memory, Node.js version, config paths

gateway.restart

PropertyValue
Scopeadmin
ParametersNone
ReturnsRestart confirmation

gateway.status

PropertyValue
Scopeadmin
ParametersNone
Returns{ pid: number, uptime: number, memoryUsage: number, nodeVersion: string, configPaths: string[], sections: string[] }
{
  "jsonrpc": "2.0",
  "method": "gateway.status",
  "id": 1
}
Observability methods for diagnostics, billing estimation, channel activity tracking, message delivery tracing, context engine inspection, prompt cache statistics, and data management. All methods require admin scope.
MethodScopeDescription
obs.billing.byAgentadminToken usage for a specific agent
obs.billing.byProvideradminToken usage breakdown by LLM provider
obs.billing.bySessionadminToken usage for a specific session
obs.billing.totaladminTotal billing estimate
obs.billing.usage24hadminLast 24 hours usage summary
obs.channels.alladminActivity data for all channels
obs.channels.getadminActivity data for a single channel
obs.channels.staleadminChannels with no recent activity
obs.context.dagadminGet DAG state snapshot for an agent
obs.context.pipelineadminGet context pipeline state for an agent
obs.delivery.recentadminRecent message delivery traces
obs.delivery.statsadminAggregate delivery statistics
obs.diagnosticsadminRecent diagnostic events with category counts
obs.getCacheStatsadminGet prompt cache statistics
obs.resetadminReset all observability data (metrics, billing, delivery, channel snapshots)
obs.reset.tableadminReset a specific observability table

obs.diagnostics

PropertyValue
Scopeadmin
Parameters{ category?: string, limit?: number, sinceMs?: number }
Returns{ events: DiagnosticEvent[], counts: Record<string, number> }

obs.billing.total

Get the total billing estimate across all agents and providers, combining in-memory data from the current daemon session with historical data from the SQLite observability store.
PropertyValue
Scopeadmin
Parameters{ sinceMs?: number }
Returns{ totalCost: number, totalTokens: number, callCount: number, totalCacheSaved: number }
{
  "jsonrpc": "2.0",
  "method": "obs.billing.total",
  "params": { "sinceMs": 86400000 },
  "id": 1
}

obs.billing.usage24h

Get an hourly breakdown of token usage for the last 24 hours. Returns one bucket per hour-of-day (0–23) with the aggregate token count for that hour.
PropertyValue
Scopeadmin
ParametersNone
ReturnsArray<{ hour: number, tokens: number }>
{
  "jsonrpc": "2.0",
  "method": "obs.billing.usage24h",
  "id": 1
}

obs.billing.byProvider

Get token usage and estimated cost broken down by LLM provider. Combines in-memory data from the current session with historical SQLite data for a complete picture.
PropertyValue
Scopeadmin
Parameters{ sinceMs?: number }
Returns{ providers: Array<{ provider: string, inputTokens: number, outputTokens: number, estimatedCostUsd: number }> }

obs.billing.byAgent

PropertyValue
Scopeadmin
Parameters{ agentId: string, sinceMs?: number } (agentId required)
Returns{ totalCost: number, totalTokens: number, callCount: number, totalCacheSaved: number }

obs.billing.bySession

PropertyValue
Scopeadmin
Parameters{ sessionKey: string, sinceMs?: number } (sessionKey required)
Returns{ totalCost: number, totalTokens: number, callCount: number, totalCacheSaved: number }

obs.channels.all

Get activity data for all channels, merging live in-memory data with historical SQLite snapshots. In-memory data is authoritative for currently-active channels; SQLite fills in channels from previous daemon sessions.
PropertyValue
Scopeadmin
ParametersNone
Returns{ channels: Array<{ channelId, channelType, lastActiveAt, messagesSent, messagesReceived }> }

obs.channels.stale

PropertyValue
Scopeadmin
Parameters{ thresholdMs?: number } (default: 300000 / 5 minutes)
Returns{ stale: ChannelActivity[] }

obs.channels.get

PropertyValue
Scopeadmin
Parameters{ channelId: string } (required)
Returns{ channel: ChannelActivity | null }

obs.delivery.recent

PropertyValue
Scopeadmin
Parameters{ sinceMs?: number, limit?: number, channelId?: string }
Returns{ deliveries: DeliveryTrace[] }

obs.delivery.stats

Get aggregate delivery statistics: total messages attempted, successes, failures, and average delivery latency. Combines in-memory counters with the SQLite observability store for a complete picture across daemon restarts.
PropertyValue
Scopeadmin
ParametersNone
Returns{ total: number, successes: number, failures: number, avgLatencyMs: number }
{
  "jsonrpc": "2.0",
  "method": "obs.delivery.stats",
  "id": 1
}
{
  "jsonrpc": "2.0",
  "method": "obs.billing.byProvider",
  "params": { "sinceMs": 86400000 },
  "id": 1
}

obs.context.dag

PropertyValue
Scopeadmin
Parameters{ agentId?: string }
ReturnsDAG state snapshot with node counts, depths, and compaction history

obs.context.pipeline

PropertyValue
Scopeadmin
Parameters{ agentId?: string }
ReturnsContext pipeline state including layer configuration and token budgets

obs.getCacheStats

PropertyValue
Scopeadmin
ParametersNone
ReturnsPrompt cache statistics with hit/miss rates, savings estimates, and per-provider breakdowns
{
  "jsonrpc": "2.0",
  "method": "obs.getCacheStats",
  "id": 1
}
Correlate trace rows from the last two days of session-index records. Look up by messageId (an O(1) LRU resolves it to a traceId first), by traceId directly, by chatId, or by a since window with an optional where filter. Results are capped at limit (max 1000, default 200).Synthetic/test-harness session rows are excluded by default; pass includeSynthetic: true to include them.
PropertyValue
Scopeadmin
Parameters{ messageId?: string, traceId?: string, chatId?: string, since?: string, where?: string, limit?: number, includeSynthetic?: boolean }includeSynthetic is optional; include synthetic/test-harness sessions, which are excluded by default.
Returns{ rows: Array<Record<string, unknown>> } — matching session-index rows (newest-first within each day file), capped at limit.
{
  "jsonrpc": "2.0",
  "method": "obs.trace.search",
  "params": { "traceId": "f942d38c-e372-43cc-99f1-ead4f0b8582f" },
  "id": 1
}

obs.explain

Assemble a self-contained, redaction-safe post-mortem (an IncidentReport) for a single agent session: outcome, cost, timing, per-tool stats, the normalized failures (newest-first), the circuit-breaker timeline, large-result offloads, a one-line summary, and a deterministic likelyRootCause. The report is derived from log evidence only — no LLM is invoked — so it reproduces the same verdict from the same session forever.outcome.endReason names the terminal cause. Three degradation causes that previously collapsed into a generic error are named here (and drive likelyRootCause): context_exhausted (the context-window pre-flight guard aborted the run before the model could continue), output_starved (the final response was truncated at the model’s max output tokens; the fix is to raise the agent’s maxTokens or enable contextEngine.outputEscalation), and timeout (the prompt-level stall budget or makespan ceiling killed the turn; likelyRootCause code prompt_timeout — when the trajectory carries the enriched execution.prompt_timeout record the verdict is numbers-backed: the stall variant names the binding knob, e.g. agents.<id>.promptTimeout.promptTimeoutMs, with the configured budget and elapsed time, and the makespan variant names agents.<id>.promptTimeout.stallCeilingMultiplier for a streaming runaway; pre-extension sessions fall back to a generic knob suggestion). A tool-failure root cause still out-ranks them — they explain the terminal state, not a tool crash. The same causes are aggregated fleet-wide by obs.fleet.health’s degradedByCause.For context_exhausted sessions the report carries an optional contextBudget section — the terminal per-LLM-call budget equation extracted from the trajectory’s context.budget records (last record wins): { windowTokens, rawContextWindowTokens, windowCapSource, systemTokens, freshTailTokens, budgetedHistoryTokens, keptCount, assembledInputTokens, outputHeadroom, verdict }. windowCapSource names what clamped the effective window below the model’s configured contextWindow: the exact contextEngine.budget.* knob (effectiveContextCapSmall / effectiveContextCapNano), served (the Ollama-served num_ctx bound the window — fix with OLLAMA_CONTEXT_LENGTH=<configured> ollama serve or a Modelfile PARAMETER num_ctx), capabilityClass (the operator’s providers.entries.<id>.capabilities.capabilityClass pin bound the window — pin a higher class or remove the pin; the contextEngine.budget.* caps do not move this bind), or none. verdict is the fit-check outcome (fits / downshifted / exhausted). When present, likelyRootCause is numbers-backed: it states the assembled-vs-window totals, the binding cap, the system+tools share of the window, and the kept-history count, and its suggested steps name the binding lever (the budget knob to raise, the Ollama serve knobs, or the capabilityClass pin) or recommend reducing the active tool surface when tool schemas dominate. The section is absent for sessions recorded before the context.budget trajectory event existed; the verdict then falls back to the generic wording.Accepts EITHER sessionKey OR traceId (at least one is required). A traceId is canonicalized to its sessionKey first, so by-trace and by-session produce the identical report.depth: "summary" (the default) bounds the serialized report to roughly 6 KB (about 1,500 tokens) and caps the failure list; depth: "full" relaxes the array caps. At BOTH depths the report is digest-only: no raw tool-output body is ever inlined (oversized previews and untrusted external content collapse to a resultDigest fingerprint), and an honest truncations[] ledger records anything the bounding pass dropped.An optional coverage block reports READ-coverage — whether the trajectory, rollup, and each offload pointer were actually located and resolved ({ trajectory: { found, records }, rollup: { present }, offloads: { pointersResolved, pointersTotal } }) — distinct from truncations[], which records what the size-bounding pass dropped. A degraded report is self-evident from it (e.g. records: 0 or pointersResolved < pointersTotal) rather than masquerading as a clean session.coverage.toolStats reconciles this report’s per-tool toolStats (the whole-session trajectory union) against the persisted per-session rollup that obs.fleet.health reads (the latest-execution rollup — it is built per execution and the session metadata is overwritten each turn). The two lenses read structurally-different sources, so they CAN differ for the same session — but only in one direction: the rollup is a subset of the trajectory (rollup.{ok,failed} <= trajectory.{ok,failed} per tool). The block ({ reconciled, rollupSource: "last-execution", divergentTools: [{ tool, rollup: { ok, failed }, trajectory: { ok, failed } }] }) makes that gap transparent so comis explain and comis fleet can never silently contradict: divergentTools[] names each tool whose persisted rollup differs from the trajectory with both count pairs, and reconciled is the directional invariant (a rollup that OVER-counts the trajectory — the forbidden direction, including a tool present in the rollup but absent from the trajectory — flips it to false and surfaces the offending tool instead of hiding it).
PropertyValue
Scopeadmin
Parameters{ sessionKey?: string, traceId?: string, depth?: "summary" | "full", includeSynthetic?: boolean } — at least one of sessionKey / traceId required. includeSynthetic is optional; include synthetic/test-harness sessions, which are excluded by default.
ReturnsAn IncidentReport: { schemaVersion, sessionKey, traceId, agentId, channel, outcome: { endReason, degraded, severity }, cost: { costUsd, totalTokens, cacheReadRatio }, timing: { durationMs, turnCount }, toolStats, failures[], breakerTimeline[], offloads[], contextBudget?, summary, likelyRootCause, suggestedNextSteps[], truncations[], coverage? }
{
  "jsonrpc": "2.0",
  "method": "obs.explain",
  "params": { "sessionKey": "default:678314278:678314278:peer:678314278", "depth": "summary" },
  "id": 1
}
The comis explain CLI command (see the CLI reference) and the obs_query agent explain / session_report actions surface this same report.

obs.fleet.health

Assemble a bounded, redaction-safe cross-session fleet-health triage (a FleetHealthReport) over a recent time window: how many sessions ran and how many degraded, the degraded sessions bucketed by named cause (degradedByCause), the merged top error kinds, the total circuit-breaker trips, a per-tool ok/failed rollup, the window cost, the recent activity (agents, channels, exit reasons), the recurring findings[] (counts + short codes + hints only — no raw WARN bodies), and a deterministic likelyRootCause. Like obs.explain, the report is derived from log + diagnostics evidence only — no LLM is invoked — so the same window reproduces the same verdict.degradedByCause is the fleet-level degradation detector: a bounded { <endReason>: count } map (counts only) over the degraded sessions in the window, keyed by the named terminal cause — e.g. { "context_exhausted": 5, "output_starved": 2 } answers “how many sessions degraded, and why” at a glance. Only degraded sessions contribute; a session whose cause is missing folds into "unknown". The two Glass Box causes worth calling out — context_exhausted (the context-window pre-flight guard aborted the run; run obs.explain on the session for the numbers-backed contextBudget verdict) and output_starved (the final response was truncated at the model’s max output tokens) — are named here and in obs.explain’s outcome.endReason + likelyRootCause, where previously both collapsed into a generic error.likelyRootCause ranks acute over chronic: any degraded session with a named cause (fleet_acute_degradation, naming the dominant degradedByCause entry) out-ranks the standing config-posture (fleet_config_posture) and recurring-health-signal (fleet_recurring_health_signal) verdicts; only a fleet-wide degradation spike (fleet_high_degraded_rate) ranks above it. Routine session_rebase continuations (a restart resuming at the store’s max seq) ingest at info severity and no longer inflate the warning findings.The boot-time config_posture diagnostic row carries servedBelowConfiguredCount in its details JSON — the number of providers whose Ollama-served window (num_ctx) was below the configured contextWindow at that boot (a count only, never provider names; the posture record severity is warning when it is > 0). When the latest posture row’s count is non-zero, findings[] gains the dedicated config_posture:served_below_configured code with that count — latest-row semantics because posture is standing state, not cumulative (a healthy restart clears the finding). The hint names the OLLAMA_CONTEXT_LENGTH / Modelfile PARAMETER num_ctx knobs; a malformed or pre-v2.21 posture row folds to 0 defensively (no finding, never an assembly error). For triaging this finding on a local deployment — model choice, window sizing, and the full knob map — see the Local models playbook.This is the cross-session sibling of obs.explain: obs.explain post-mortems ONE session; obs.fleet.health rolls up a WINDOW of sessions.sinceHours is optional; the 24h default is applied in the handler. The report is digest-only: findings[] is capped top-N and topErrorKinds is merged + capped (counts only), with an honest truncations[] ledger recording anything the bounding pass dropped. An optional coverage block reports READ-coverage of the fleet sources — the session-summary store ({ found, rows }), the multi-day session index ({ daysRead, daysMissing }), and the billing source ({ present }) — so a silently-empty window (e.g. rows: 0 or daysMissing > 0) is self-evident rather than masquerading as a clean zero-activity fleet.
PropertyValue
Scopeadmin
Parameters{ sinceHours?: number } — the aggregation window in hours (positive). Optional; defaults to 24 in the handler.
ReturnsA FleetHealthReport: { schemaVersion, windowHours, sessions: { total, degraded, degradedRate }, degradedByCause, topErrorKinds[], breakerTripTotal, toolStats, cost: { costUsd, totalTokens }, activity: { activeAgents[], activeChannels[], exitReasons, turnTotal, tokenTotal }, findings[], likelyRootCause, suggestedNextSteps[], truncations[], coverage? }
{
  "jsonrpc": "2.0",
  "method": "obs.fleet.health",
  "params": { "sinceHours": 24 },
  "id": 1
}
The comis fleet CLI command (see the CLI reference) and the obs_query agent fleet_health action surface this same report. It is the cross-session sibling of comis explain — NOT to be confused with comis health, the LOCAL daemon doctor (which runs no RPC).

obs.reset

PropertyValue
Scopeadmin
ParametersNone
Returns{ reset: true, rowsDeleted: { tokenUsage: number, delivery: number, diagnostics: number, channels: number } }
{
  "jsonrpc": "2.0",
  "method": "obs.reset",
  "id": 1
}

obs.reset.table

PropertyValue
Scopeadmin
Parameters{ table: string } — valid values: "token_usage", "delivery", "diagnostics", "channels"
Returns{ reset: true, table: string, rowsDeleted: number }
{
  "jsonrpc": "2.0",
  "method": "obs.reset.table",
  "params": { "table": "delivery" },
  "id": 1
}
These methods permanently delete observability data. The web console requires typing RESET as confirmation before calling obs.reset.
Session management for agent conversations. Client-facing methods use rpc scope; administrative operations use admin scope.
MethodScopeDescription
session.sendrpcSend a message to an existing session
session.spawnrpcSpawn a sub-agent session
session.statusrpcGet session status
session.historyrpcGet session conversation history
session.searchrpcSearch session content by query
session.run_statusrpcGet live status of a specific sub-agent run
session.listadminList all active sessions
session.deleteadminDelete a session
session.resetadminReset all sessions
session.exportadminExport session data
session.compactadminCompact session history
session.reset_conversationadminComplete cross-mode conversation reset (LCD history + working session transcript + pi runtime session)

session.status

Get the current resource usage and configuration summary for the calling agent’s session: model, token consumption, steps executed, and the configured step limit.
PropertyValue
Scoperpc
ParametersNone (resolved from the calling agent context)
Returns{ model: string, agentName: string, tokensUsed: { totalTokens, totalCost }, stepsExecuted: number, maxSteps: number }
{
  "jsonrpc": "2.0",
  "method": "session.status",
  "id": 1
}

session.history

Retrieve the conversation history for a session. Returns the raw message array stored in the session, including both user and assistant turns.
PropertyValue
Scoperpc
Parameters{ channelId?: string }
Returns{ messages: Array<{ role: string, content: string, timestamp?: number }> }

session.list

List all sessions the daemon knows about, including sessions stored in SQLite, JSONL transcript files, and workspace session files. Optionally filter by recency or session kind.
PropertyValue
Scopeadmin
Parameters{ kind?: "all" | "sub-agent" | "group" | "dm", since_minutes?: number }
Returns{ sessions: Array<{ sessionKey, agentId, messageCount, updatedAt, metadata }> }
{
  "jsonrpc": "2.0",
  "method": "session.list",
  "params": { "kind": "dm", "since_minutes": 60 },
  "id": 1
}

session.send

PropertyValue
Scoperpc
Parameters{ key: string, message: string, agentId?: string }
ReturnsAgent response

session.spawn

PropertyValue
Scoperpc
Parameters{ parentKey: string, task: string, agentId?: string }
ReturnsSpawned session info

session.delete

PropertyValue
Scopeadmin
Parameters{ session_key: string }
Returns{ sessionKey: string, deleted: true, transcript: object }
The parameter name is session_key (snake_case) — the handler rejects requests that pass key instead. The deleted session’s transcript is returned in the response so you have a final copy.

session.reset

Clear all messages in a session while preserving the session’s metadata (identity, channel association). Useful for giving an agent a clean slate without fully deleting the session record. Also clears any cached approval decisions for the session.
PropertyValue
Scopeadmin
Parameters{ session_key: string }
Returns{ sessionKey: string, reset: true, previousMessageCount: number }

session.export

Export a session’s full message history and metadata as a JSON object. Useful for archiving, debugging, or migrating sessions between instances.
PropertyValue
Scopeadmin
Parameters{ session_key: string }
Returns{ sessionKey, messages, metadata, messageCount, createdAt, updatedAt }
{
  "jsonrpc": "2.0",
  "method": "session.export",
  "params": { "session_key": "telegram:user123:chat456" },
  "id": 1
}

session.run_status

Get the live status of a specific sub-agent run by its run ID. Returns timing, the task description, the current status, and — once complete — the response text and token usage.
PropertyValue
Scoperpc
Parameters{ run_id: string }
Returns{ runId, status, agentId, task, sessionKey, startedAt, completedAt?, runtimeMs, response?, tokensUsed?, cost?, error? }
{
  "jsonrpc": "2.0",
  "method": "session.run_status",
  "params": { "run_id": "run_abc123" },
  "id": 1
}
PropertyValue
Scoperpc
Parameters{ query: string, limit?: number }
ReturnsArray<{ sessionKey: string, agentId: string, channelType: string, snippet: string, score: number, timestamp: number }>
{
  "jsonrpc": "2.0",
  "method": "session.search",
  "params": { "query": "deployment instructions", "limit": 5 },
  "id": 1
}

session.compact

PropertyValue
Scopeadmin
Parameters{ key: string }
ReturnsCompaction result

session.reset_conversation

Complete cross-mode conversation reset. Clears all three transcript layers: the LCD durable history, the daemon sessionStore working transcript, and the pi runtime session. Destructive and irreversible. Admin-scoped — requires an admin token.This is the correct explicit forget command. Unlike session.delete (which only removes the session record), this operation ensures the model starts with a clean slate in both engine modes: the LCD store is empty (dag mode), the sessionStore messages are empty, and the runtime session transcript is destroyed. The runtime layer matters: without it, the surviving runtime JSONL is re-ingested wholesale on the next turn (LCD epoch rebase) and the “forgotten” conversation resurrects.The operation is serialized against live LCD ingest (safe to call while the daemon is running). Returns count-only — no message content is returned or logged. Best-effort on each layer: absent sessionStore entry or zero LCD rows is not an error.
PropertyValue
Scopeadmin
Parameters{ session_key: string, memory?: boolean, purge_derived?: boolean }memory defaults to false; when true, the conversation’s RAG memories are also deleted by source_session_key (both paired-conversation and LCD-distilled episodic memories) for the agent + tenant scope, and the deleted sources are unlinked from consolidated observations (orphan observation → deleted; multi-source observation → kept with the reference removed). purge_derived (default false, only meaningful with memory: true) escalates to deleting every observation derived from this session, even those corroborated by other sessions.
Returns{ sessionKey: string, lcdRowsDeleted: number, sessionMessagesCleared: number, memoriesDeleted?: number, runtimeSessionDestroyed?: boolean }memoriesDeleted is the count of deleted RAG memory rows when memory: true and a memory store is wired. It is omitted (undefined) only when memory was not requested, or when the daemon has no memory store wired (the LCD + session transcript are still cleared). runtimeSessionDestroyed reports whether the pi runtime session was destroyed; false means that layer was unavailable and the conversation may resurrect on the next turn (a WARN with the consequence is logged).
{
  "jsonrpc": "2.0",
  "method": "session.reset_conversation",
  "params": {
    "session_key": "default:user123:telegram",
    "memory": true
  },
  "id": 1
}
A RAG-memory clear failure is non-fatal: if the memory delete fails, the LCD + session-transcript reset that already succeeded is preserved and the failure is logged (the response then reports memoriesDeleted: 0). purge_derived is destructive and cannot be undone — an observation learned from multiple sessions is deleted in full, not merely unlinked. memory / purge_derived are the only parameters that delete memories; on the recall side, paired-conversation memories overlapping a distilled LCD summary from the same session are automatically down-weighted (never deleted), so a distilled summary does not double-count with its own source rows.
After a reset, the next conversation turn starts with a complete clean slate in both dag and pipeline modes. For the full durability model (LCD vs. JSONL vs. RAG memory), see Data Directory.
Scheduled job management for cron expressions, intervals, and one-time tasks.
MethodScopeDescription
cron.listrpcList all cron jobs
cron.addrpcAdd a new cron job
cron.updaterpcUpdate an existing cron job
cron.removerpcRemove a cron job
cron.statusrpcGet cron job status
cron.runsrpcGet cron job run history
cron.runrpcTrigger a manual cron run

cron.add

PropertyValue
Scoperpc
Parameters{ name: string, message: string, agentId?: string, schedule: { kind: "cron" | "interval" | "once", expr?: string, tz?: string, everyMs?: number, at?: string } }
ReturnsCreated job info
{
  "jsonrpc": "2.0",
  "method": "cron.add",
  "params": {
    "name": "daily-summary",
    "message": "Summarize today's activity",
    "schedule": {
      "kind": "cron",
      "expr": "0 18 * * *",
      "tz": "America/New_York"
    }
  },
  "id": 1
}

cron.list

List all scheduled jobs. Returns each job’s name, schedule expression, next run time, and whether it is currently enabled.
PropertyValue
Scoperpc
ParametersNone
Returns{ jobs: Array<{ id, name, scheduleKind, expr?, tz?, everyMs?, nextRunAtMs, enabled, lastRunAtMs?, lastError? }> }
{
  "jsonrpc": "2.0",
  "method": "cron.list",
  "id": 1
}

cron.update

Update an existing cron job’s schedule or message. Only the fields you provide are changed.
PropertyValue
Scoperpc
Parameters{ name: string, message?: string, agentId?: string, schedule?: { kind: "cron" | "interval" | "once", expr?: string, tz?: string, everyMs?: number, at?: string } }
ReturnsUpdated job info

cron.status

Get the current status of a single cron job by name.
PropertyValue
Scoperpc
Parameters{ name: string }
Returns{ id, name, scheduleKind, nextRunAtMs, enabled, lastRunAtMs?, lastError? }

cron.runs

Get the run history for a cron job — timestamps, durations, and whether each run succeeded.
PropertyValue
Scoperpc
Parameters{ name: string, limit?: number }
Returns{ runs: Array<{ runAt: number, durationMs: number, success: boolean, error?: string }> }
{
  "jsonrpc": "2.0",
  "method": "cron.runs",
  "params": { "name": "daily-summary", "limit": 5 },
  "id": 1
}

cron.remove

PropertyValue
Scoperpc
Parameters{ name: string }
ReturnsRemoval confirmation

cron.run

Trigger an immediate manual run of a scheduled job. By default this forces the job to execute regardless of its next scheduled time (mode: "force"). Pass mode: "due" to run all currently overdue jobs instead.
PropertyValue
Scoperpc
Parameters{ name?: string, mode?: "force" | "due" } (name required when mode is "force")
Returns{ triggered: true, mode: string, jobName?: string }
Browser automation via Chrome DevTools Protocol (CDP). All methods use rpc scope and bridge to the browser automation subsystem.
MethodScopeDescription
browser.statusrpcBrowser session status (running, URL, tab count)
browser.startrpcStart a browser session
browser.stoprpcStop the browser session
browser.navigaterpcNavigate to a URL
browser.snapshotrpcTake a DOM snapshot (accessibility tree)
browser.screenshotrpcTake a screenshot (returns base64 PNG)
browser.pdfrpcGenerate a PDF of the current page
browser.actrpcExecute a browser action (click, type, scroll)
browser.tabsrpcList open browser tabs
browser.openrpcOpen a new tab
browser.focusrpcFocus a specific tab
browser.closerpcClose a tab
browser.consolerpcGet console log entries

browser.status

Get the current browser session status: whether a session is running, the current URL, and the number of open tabs.
PropertyValue
Scoperpc
ParametersNone
Returns{ running: boolean, url?: string, tabCount?: number }

browser.start

Start a browser session. A headless Chromium instance is launched and connected via CDP. Does nothing if a session is already running.
PropertyValue
Scoperpc
ParametersNone
Returns{ started: true }

browser.stop

Stop the active browser session and close all tabs. Any ongoing automation is interrupted.
PropertyValue
Scoperpc
ParametersNone
Returns{ stopped: true }

browser.navigate

PropertyValue
Scoperpc
Parameters{ url: string }
ReturnsNavigation result with final URL
{
  "jsonrpc": "2.0",
  "method": "browser.navigate",
  "params": { "url": "https://example.com" },
  "id": 1
}

browser.snapshot

Take an accessibility-tree DOM snapshot of the current page. Returns a structured representation of interactive elements — more reliable for automation than raw HTML.
PropertyValue
Scoperpc
ParametersNone
ReturnsAccessibility tree snapshot object

browser.screenshot

PropertyValue
Scoperpc
Parameters{ fullPage?: boolean }
Returns{ data: string } (base64-encoded PNG)

browser.pdf

Generate a PDF of the current page and return it as base64-encoded data.
PropertyValue
Scoperpc
ParametersNone
Returns{ data: string } (base64-encoded PDF)

browser.act

PropertyValue
Scoperpc
Parameters{ action: string, selector?: string, text?: string, value?: string }
ReturnsAction result

browser.tabs

List all currently open browser tabs with their IDs, URLs, and titles.
PropertyValue
Scoperpc
ParametersNone
Returns{ tabs: Array<{ id: string, url: string, title: string }> }

browser.open

Open a new browser tab, optionally navigating to a URL immediately.
PropertyValue
Scoperpc
Parameters{ url?: string }
Returns{ tabId: string }

browser.focus

Focus a specific tab by its ID, making it the active tab for subsequent commands.
PropertyValue
Scoperpc
Parameters{ tabId: string }
Returns{ focused: true, tabId: string }

browser.close

Close a specific tab by its ID.
PropertyValue
Scoperpc
Parameters{ tabId: string }
Returns{ closed: true, tabId: string }

browser.console

Retrieve console log entries captured since the browser session started. Useful for debugging page-level JavaScript errors during automation.
PropertyValue
Scoperpc
ParametersNone
Returns{ entries: Array<{ level: string, text: string, timestamp: number }> }
Speech-to-text transcription using the configured STT provider.
MethodScopeDescription
audio.transcriberpcTranscribe audio to text

audio.transcribe

PropertyValue
Scoperpc
Parameters{ audio: string, mimeType?: string, language?: string } (audio is base64-encoded, mimeType defaults to "audio/ogg")
Returns{ text: string, language?: string, durationMs?: number }
Returns { error: "..." } if STT is not configured or transcription fails.
{
  "jsonrpc": "2.0",
  "method": "audio.transcribe",
  "params": {
    "audio": "T2dnUwACAAAAAAA...",
    "mimeType": "audio/ogg",
    "language": "en"
  },
  "id": 1
}
Approval gate management for action confirmation workflows.
MethodScopeDescription
admin.approval.clearDenialCacheadminClear the denial cache for approval gates
admin.approval.pendingadminList pending approval requests
admin.approval.resolveadminApprove or deny a pending request
admin.approval.resolveAlladminBulk-resolve all pending approval requests for a session

admin.approval.clearDenialCache

PropertyValue
Scopeadmin
ParametersNone
Returns{ cleared: true }
{
  "jsonrpc": "2.0",
  "method": "admin.approval.clearDenialCache",
  "id": 1
}

admin.approval.pending

PropertyValue
Scopeadmin
Parameters{}
ReturnsList of pending approval requests

admin.approval.resolve

PropertyValue
Scopeadmin
Parameters{ id: string, approved: boolean, reason?: string }
ReturnsResolution confirmation

admin.approval.resolveAll

Bulk-approve or bulk-deny every pending request at once, optionally scoped to a single session. Useful during incident response when many requests have queued up and you need to unblock or cancel them all in one call.
PropertyValue
Scopeadmin
Parameters{ approved: boolean, sessionKey?: string, approvedBy?: string, reason?: string }
Returns{ resolved: number, requestIds: string[] }
sessionKey filters to only the requests belonging to that session. Omit it to resolve all pending requests across every session. approvedBy defaults to "operator" when omitted.
{
  "jsonrpc": "2.0",
  "method": "admin.approval.resolveAll",
  "params": { "approved": false, "reason": "Cancelled by operator" },
  "id": 1
}
Agent lifecycle management: create, read, update, delete, suspend, and resume agents.
MethodScopeDescription
agents.listadminList all configured agents
agents.createadminCreate a new agent
agents.getadminGet agent configuration
agents.updateadminUpdate agent configuration
agents.deleteadminDelete an agent
agents.suspendadminSuspend an agent (stop processing)
agents.resumeadminResume a suspended agent

agents.list

List all configured agent IDs. This is a lightweight call that returns only the IDs — use agents.get for full configuration details on a specific agent.
PropertyValue
Scopeadmin
ParametersNone
Returns{ agents: string[] }

agents.create

PropertyValue
Scopeadmin
Parameters{ name: string, provider?: string, model?: string, ...config }
ReturnsCreated agent configuration

agents.get

PropertyValue
Scopeadmin
Parameters{ agentId: string }
ReturnsAgent configuration object
{
  "jsonrpc": "2.0",
  "method": "agents.list",
  "id": 1
}

agents.update

Update an existing agent’s configuration. Only the fields you provide are changed; everything else stays as-is. The agent continues running with the new settings immediately — no restart required.Pass dryRun: true to validate a configuration patch without applying it: the daemon runs the full validation path (schema parse, OAuth-profile existence checks, and the provider credential guard/probe when the provider changes) and returns the would-be result, but does not persist to config.yaml/config.last-good.yaml and does not hot-apply the change to the running agent. The web dashboard’s “Validate” button uses this so checking a config never mutates a live agent.
PropertyValue
Scopeadmin
Parameters{ agentId: string, name?: string, provider?: string, model?: string, dryRun?: boolean, ...config }
ReturnsUpdated agent configuration (or, with dryRun: true, the validation outcome with no side effects)
{
  "jsonrpc": "2.0",
  "method": "agents.update",
  "params": {
    "agentId": "researcher",
    "model": "claude-opus-4-5-20250929"
  },
  "id": 1
}

agents.delete

Permanently remove an agent from the configuration. Any active sessions belonging to the agent are left intact in the session store but will fail to execute new turns after deletion.
PropertyValue
Scopeadmin
Parameters{ agentId: string }
Returns{ agentId: string, deleted: true }

agents.suspend

Suspend an agent so it stops accepting new messages. Existing in-flight executions are allowed to finish. Useful for taking an agent offline temporarily without deleting its configuration.
PropertyValue
Scopeadmin
Parameters{ agentId: string }
Returns{ agentId: string, suspended: true }

agents.resume

Resume a previously suspended agent, allowing it to accept messages again.
PropertyValue
Scopeadmin
Parameters{ agentId: string }
Returns{ agentId: string, resumed: true }
{
  "jsonrpc": "2.0",
  "method": "agents.suspend",
  "params": { "agentId": "researcher" },
  "id": 1
}
Memory system operations: search, inspect, browse, manage, store, and export. Core search and inspect use rpc scope; management methods use admin scope.
MethodScopeDescription
memory.browseadminBrowse memory entries with pagination
memory.deleteadminDelete a memory entry
memory.embeddingCacheadminGet embedding cache statistics
memory.exportadminExport memory database
memory.flushadminFlush all memory entries
memory.inspectrpcInspect memory entry or statistics
memory.searchrpcSearch memory entries (full-text + vector)
memory.statsadminMemory system statistics
memory.storeadminStore a new memory entry
PropertyValue
Scoperpc
Parameters{ query: string, limit?: number }
Returns{ results: MemoryEntry[] }
{
  "jsonrpc": "2.0",
  "method": "memory.search",
  "params": { "query": "deployment instructions", "limit": 5 },
  "id": 1
}

memory.browse

PropertyValue
Scopeadmin
Parameters{ offset?: number, limit?: number }
ReturnsPaginated memory entries

memory.delete

PropertyValue
Scopeadmin
Parameters{ id: string }
ReturnsDeletion confirmation

memory.embeddingCache

PropertyValue
Scopeadmin
ParametersNone
ReturnsCache statistics (size, hit rate, evictions)

memory.inspect

Inspect a single memory entry by ID, or retrieve overall memory system statistics when no ID is given.
PropertyValue
Scoperpc
Parameters{ id?: string, tenantId?: string }
Returns{ entry?: MemoryEntry } (with id) or { stats?: object } (without id)
{
  "jsonrpc": "2.0",
  "method": "memory.inspect",
  "params": { "id": "mem_abc123" },
  "id": 1
}

memory.stats

Get aggregate statistics for the memory system: total entry count, database size, embedding cache hit rate, and provider information.
PropertyValue
Scopeadmin
ParametersNone
Returns{ totalEntries: number, dbSizeBytes: number, embeddingProvider?: string, cacheHitRate?: number }

memory.flush

Delete all memory entries permanently. This is a destructive operation with no undo — all stored memories are wiped from both the vector index and the database.
PropertyValue
Scopeadmin
ParametersNone
Returns{ flushed: true, deletedCount: number }
memory.flush is irreversible. Export your memories with memory.export before flushing if you want a backup.

memory.export

Export the entire memory database as a portable JSON snapshot. Useful for backups, migration between instances, or offline analysis.
PropertyValue
Scopeadmin
ParametersNone
Returns{ entries: MemoryEntry[], exportedAt: number, totalEntries: number }

memory.store

PropertyValue
Scopeadmin
Parameters{ content: string, metadata?: object }
ReturnsStored entry ID
{
  "jsonrpc": "2.0",
  "method": "memory.store",
  "params": {
    "content": "Important note about deployment procedure",
    "metadata": { "category": "ops", "priority": "high" }
  },
  "id": 1
}
Model catalog inspection and connectivity testing. The catalog is sourced live from the @earendil-works/pi-ai SDK — getProviders() for the provider list, getModels(provider) for per-provider model details. No hardcoded provider/model tables on the comis side.
MethodScopeDescription
models.list_providersadminList all providers known to the pi-ai catalog
models.listadminList available models from the catalog (optionally filtered to one provider)
models.testadminTest connectivity to a specific model

models.list_providers

List all providers in the pi-ai SDK catalog. Returns provider ids and a count. Use this to populate provider pickers (the web wizard’s Provider step and CLI wizard’s 03-provider step both consume this).
PropertyValue
Scopeadmin
ParametersNone
Returns{ providers: string[], count: number }
{
  "jsonrpc": "2.0",
  "method": "models.list_providers",
  "id": 1
}

models.list

List all models available across the pi-ai catalog (optionally filtered to one provider). Returns the model ID, provider name, display name, baseUrl, context window, max tokens, input modalities, reasoning support, and cost per million tokens. Use this to discover what models you can assign to agents.
PropertyValue
Scopeadmin
Parameters{ provider?: string } (omit for all providers)
ReturnsArray<{ provider, modelId, displayName, contextWindow, maxTokens, baseUrl, input, reasoning, cost: { input, output, cacheRead, cacheWrite }, validated, validatedAt }>
{
  "jsonrpc": "2.0",
  "method": "models.list",
  "params": { "provider": "anthropic" },
  "id": 1
}

models.test

Test connectivity to a specific model by sending a minimal prompt and measuring the round-trip latency. Useful for verifying that your API keys and network path are working before assigning a model to an agent.
PropertyValue
Scopeadmin
Parameters{ model: string, provider?: string }
Returns{ ok: boolean, latencyMs: number, provider: string, error?: string }
{
  "jsonrpc": "2.0",
  "method": "models.test",
  "params": { "model": "claude-sonnet-4-5-20250929", "provider": "anthropic" },
  "id": 1
}
Gateway token management for API authentication.
MethodScopeDescription
tokens.listadminList all gateway tokens (secrets redacted)
tokens.createadminCreate a new gateway token
tokens.revokeadminRevoke a gateway token
tokens.rotateadminRotate a token (revoke old, create new)

tokens.list

List all configured gateway tokens. Token secrets are always redacted — you can see token IDs, scopes, and creation timestamps, but never the raw secret.
PropertyValue
Scopeadmin
ParametersNone
Returns{ tokens: Array<{ id: string, scopes: string[], createdAt: string }> }
{
  "jsonrpc": "2.0",
  "method": "tokens.list",
  "id": 1
}

tokens.create

Create a new gateway token. The secret is returned only in this response — it cannot be retrieved again. Store it securely immediately.
PropertyValue
Scopeadmin
Parameters{ id: string, scopes: string[] }
Returns{ id: string, secret: string, scopes: string[] }

tokens.revoke

Permanently revoke a gateway token. Any client currently authenticated with this token will be disconnected at their next request.
PropertyValue
Scopeadmin
Parameters{ id: string }
Returns{ id: string, revoked: true }

tokens.rotate

Revoke an existing token and create a replacement with the same ID and scopes in a single atomic operation. The new secret is returned once and cannot be retrieved again.
PropertyValue
Scopeadmin
Parameters{ id: string }
Returns{ id: string, secret: string, scopes: string[], rotated: true }
{
  "jsonrpc": "2.0",
  "method": "tokens.rotate",
  "params": { "id": "dashboard" },
  "id": 1
}
Channel adapter management: list, inspect, enable, disable, restart, capabilities, and health for chat platform connections.
MethodScopeDescription
channels.capabilitiesrpcGet per-channel capability matrix
channels.disableadminDisable a channel adapter
channels.enableadminEnable a channel adapter
channels.getadminGet detailed channel information
channels.healthrpcGet channel health summary
channels.listadminList all configured channels with status
channels.restartadminRestart a channel adapter connection

channels.list

List all configured channel adapters with their current status. Includes both running adapters and channels that are configured but not currently active.
PropertyValue
Scopeadmin
ParametersNone
Returns{ channels: Array<{ channelType, channelId?, status: "running" | "stopped" }>, total: number }

channels.capabilities

PropertyValue
Scoperpc
Parameters{ channel_type: string }
Returns{ channelType: string, features: object } — the feature capability map for the specified channel type
{
  "jsonrpc": "2.0",
  "method": "channels.capabilities",
  "id": 1
}

channels.get

PropertyValue
Scopeadmin
Parameters{ channel_type: string }
Returns{ channelType, channelId?, status: "running" | "stopped", configured?: boolean }

channels.health

PropertyValue
Scoperpc
ParametersNone
ReturnsChannel health summary with connectivity status
{
  "jsonrpc": "2.0",
  "method": "channels.health",
  "id": 1
}

channels.enable

Start a stopped channel adapter. The adapter must already be configured — this restarts its connection without touching the config file. The health monitor is notified automatically.
PropertyValue
Scopeadmin
Parameters{ channel_type: string }
Returns{ channelType: string, status: "running", message: string }

channels.disable

Stop a running channel adapter. The adapter is shut down cleanly and removed from the health monitor. The config file is updated to reflect the new enabled: false state.
PropertyValue
Scopeadmin
Parameters{ channel_type: string }
Returns{ channelType: string, status: "stopped", message: string }
{
  "jsonrpc": "2.0",
  "method": "channels.disable",
  "params": { "channel_type": "telegram" },
  "id": 1
}

channels.restart

Stop then immediately restart a channel adapter. Useful when a connection has gone stale and you want to force a clean reconnect without disabling the channel.
PropertyValue
Scopeadmin
Parameters{ channel_type: string }
Returns{ channelType: string, status: "running", message: string }
{
  "jsonrpc": "2.0",
  "method": "channels.list",
  "id": 1
}
Model Context Protocol (MCP) server management: list, connect, disconnect, and test MCP tool servers.
MethodScopeDescription
mcp.listadminList all configured MCP servers
mcp.statusadminGet MCP server connection status
mcp.connectadminConnect to an MCP server
mcp.disconnectadminDisconnect from an MCP server
mcp.reconnectadminReconnect to an MCP server
mcp.testadminTest MCP server connectivity

mcp.list

List all configured MCP servers with their current connection status and tool counts.
PropertyValue
Scopeadmin
ParametersNone
Returns{ servers: Array<{ id: string, status: string, tools: number }> }

mcp.status

Get the current connection status of a specific MCP server, including which tools it exposes.
PropertyValue
Scopeadmin
Parameters{ serverId: string }
Returns{ serverId, status, tools: string[], error?: string }

mcp.connect

Connect to an MCP server. If the server is already connected this is a no-op. On success the response includes the list of tool names the server exposes.
PropertyValue
Scopeadmin
Parameters{ serverId: string }
ReturnsConnection result with available tools

mcp.disconnect

Gracefully disconnect from an MCP server. The server remains in the configuration but will not be used until you reconnect.
PropertyValue
Scopeadmin
Parameters{ serverId: string }
Returns{ serverId: string, disconnected: true }

mcp.reconnect

Disconnect then immediately reconnect to an MCP server. Use this to pick up configuration changes or recover from a stale connection without editing the config file.
PropertyValue
Scopeadmin
Parameters{ serverId: string }
ReturnsReconnection result with refreshed tool list

mcp.test

Test connectivity to an MCP server without changing its state. Returns the round-trip latency and confirms the server is reachable.
PropertyValue
Scopeadmin
Parameters{ serverId: string }
Returns{ serverId: string, ok: boolean, latencyMs: number, error?: string }
{
  "jsonrpc": "2.0",
  "method": "mcp.list",
  "id": 1
}
Prompt skill management: list, create, upload, import from GitHub, update, and delete skills.
MethodScopeDescription
skills.listrpcList prompt skills for an agent
skills.createadminCreate a new skill from SKILL.md content (single-file shortcut)
skills.uploadadminUpload a skill folder (files + SKILL.md)
skills.importadminImport a skill from a GitHub repository URL
skills.updateadminUpdate an existing skill’s SKILL.md content
skills.deleteadminDelete a skill

skills.list

PropertyValue
Scoperpc
Parameters{ agentId?: string }
Returns{ skills: SkillDescription[] }

skills.upload

PropertyValue
Scopeadmin
Parameters{ name: string, agentId?: string, scope?: "local" | "shared", files: Array<{ path: string, content: string }> }
Returns{ ok: true, path: string }
The name must be 1-64 characters, lowercase alphanumeric with hyphens. The files array must include a SKILL.md file.The optional scope parameter controls where the skill is written. "local" (default) writes to the calling agent’s workspace skills directory. "shared" writes to the global skills directory visible to all agents. Only the default agent (set via routing.defaultAgentId) can use scope: "shared".
{
  "jsonrpc": "2.0",
  "method": "skills.upload",
  "params": {
    "name": "my-skill",
    "agentId": "researcher",
    "scope": "local",
    "files": [
      { "path": "SKILL.md", "content": "---\nname: my-skill\ndescription: A custom skill\n---\nInstructions here." }
    ]
  },
  "id": 1
}

skills.import

PropertyValue
Scopeadmin
Parameters{ url: string, agentId?: string, scope?: "local" | "shared" }
Returns{ ok: true, path: string, name: string, fileCount: number }
Accepts GitHub directory URLs in the format: https://github.com/{owner}/{repo}/tree/{branch}/{path}The optional scope parameter works the same as in skills.upload — “local” (default) imports to the agent’s workspace, “shared” imports to the global directory (default agent only).

skills.create

Create a new skill by providing its full SKILL.md content directly — a convenient shortcut over skills.upload when your skill is a single file. The content is security-scanned before being written to disk. Fails if a skill with that name already exists; use skills.update to modify an existing skill.
PropertyValue
Scopeadmin
Parameters{ name: string, content: string, agentId?: string, scope?: "local" | "shared" }
Returns{ ok: true, path: string, name: string }
name must be 1–64 characters, lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens. content must be a valid SKILL.md string and passes through the same security scanner as skills.upload.
{
  "jsonrpc": "2.0",
  "method": "skills.create",
  "params": {
    "name": "haiku-writer",
    "agentId": "poet",
    "content": "---\nname: haiku-writer\ndescription: Compose haiku on any topic\n---\nWrite a three-line haiku about the user's topic."
  },
  "id": 1
}

skills.update

Replace the SKILL.md content of an existing skill. The skill directory must already exist — use skills.create or skills.upload for new skills. The updated content is security-scanned before being written.
PropertyValue
Scopeadmin
Parameters{ name: string, content: string, agentId?: string, scope?: "local" | "shared" }
Returns{ ok: true, path: string, name: string }

skills.delete

PropertyValue
Scopeadmin
Parameters{ name: string, agentId?: string, scope?: "local" | "shared" }
Returns{ ok: true }
When deleting with scope: "local" (default), the skill must exist in the agent’s workspace directory. Attempting to delete a shared skill with local scope returns an error with guidance to use scope: "shared". Only the default agent can delete shared skills.
Graph execution engine for multi-step agent pipelines (DAGs).
MethodScopeDescription
graph.cancelrpcCancel a running graph execution
graph.definerpcDefine an execution graph
graph.deleterpcDelete a saved graph definition
graph.deleteRunrpcDelete a graph execution run and its artifacts
graph.executerpcExecute a defined graph
graph.listrpcList saved graph definitions
graph.loadrpcLoad a named graph definition
graph.outputsrpcRetrieve node output values from a graph
graph.runDetailrpcGet detailed info for a specific execution run
graph.runsrpcList recent graph execution runs
graph.saverpcSave a named graph definition
graph.statusrpcGet graph execution status

graph.define

PropertyValue
Scoperpc
Parameters{ nodes: NodeDefinition[], edges: EdgeDefinition[] }
Returns{ graphId: string }
Each NodeDefinition includes node_id, task, and optional fields: depends_on, agent, model, timeout_ms, max_steps, barrier_mode, retries, type_id, type_config, context_mode. When type_id is set, type_config is validated against the driver’s config schema. See Node Types for available types.typeConfig validation errors: When type_id is set and type_config does not match the driver’s schema, the method returns an error with a schemaToExample hint showing the expected config shape. This hint helps LLMs self-correct invalid configurations.
{
  "error": {
    "code": -32602,
    "message": "Node \"evaluate\" type_config invalid: agents: Required. Expected: {\"agents\":\"array\",\"rounds\":\"number (optional)\",\"synthesizer\":\"string (optional)\"}"
  }
}
The Expected: suffix is generated by schemaToExample() and shows each field’s expected type with optionality markers.Graph warnings for typed nodes: Both graph.define and graph.execute return a warnings array for soft validation issues that an LLM can fix before execution:
Warning TypeDescription
typed_node_agentid_ignoredagentId set on a typed node is ignored — agents come from type_config
typed_node_expensive_retryretries > 0 on a typed node re-runs the entire driver from scratch
typed_node_approval_retryRetries on an approval-gate node will re-prompt the user

graph.execute

PropertyValue
Scoperpc
Parameters{ graphId: string, inputs?: Record<string, unknown> }
ReturnsExecution result with per-node outputs
If the graph contains approval-gate nodes, the request must include announceChannelType and announceChannelId for user interaction routing.
{
  "jsonrpc": "2.0",
  "method": "graph.execute",
  "params": { "graphId": "research-pipeline" },
  "id": 1
}

graph.status

Returns graph execution status. This method has two response forms depending on whether a graphId parameter is provided.
PropertyValue
Scoperpc
Parameters{ graphId?: string, recentMinutes?: number }
ReturnsPer-node status (with graphId) or graph list with concurrency stats (without graphId)
With graphId — Returns detailed per-node execution state for a single graph, including node outputs (truncated to 500 characters), timing, and aggregate stats.
{
  "jsonrpc": "2.0",
  "method": "graph.status",
  "params": { "graphId": "abc-123" },
  "id": 1
}
Without graphId — Returns a list of all recent graphs with aggregate status, plus live concurrency statistics. Use the optional recentMinutes parameter to filter to graphs active within the specified time window.
{
  "jsonrpc": "2.0",
  "method": "graph.status",
  "id": 1
}
The concurrency object reports the current state of the three-tier concurrency model: globalActiveSubAgents is the count of currently running sub-agents across all graphs, maxGlobalSubAgents is the configured cap, and queueDepth is the number of spawns waiting in the FIFO queue.

graph.outputs

Retrieve node output values from a completed or running graph. Uses memory-first retrieval with disk fallback for expired graphs.
PropertyValue
Scoperpc
Parameters{ graphId: string }
Returns{ graphId: string, outputs: Record<string, string | null>, source: "memory" | "disk" }
{
  "jsonrpc": "2.0",
  "method": "graph.outputs",
  "params": { "graphId": "abc-123-def" },
  "id": 1
}
outputs is a Record<string, string \| null>null means the node has not completed yet. source is "memory" (from the in-memory coordinator) or "disk" (from *-output.md files in graph-runs/<graphId>/). Output values are truncated at 12,000 characters per node (compared to 500 for graph.status).

graph.cancel

Cancel a running graph execution. Nodes that are already in-flight are allowed to finish, but no new nodes will be dispatched after the cancellation is processed.
PropertyValue
Scoperpc
Parameters{ graphId: string }
Returns{ graphId: string, cancelled: true }

graph.save

Save a graph definition under a human-readable name so you can reload it later with graph.load. The graphId refers to a graph you have already defined with graph.define.
PropertyValue
Scoperpc
Parameters{ name: string, graphId: string }
Returns{ name: string, saved: true }

graph.load

Load a previously saved named graph definition and return a fresh graphId you can execute. This is equivalent to calling graph.define with the saved node/edge structure.
PropertyValue
Scoperpc
Parameters{ name: string }
Returns{ graphId: string, name: string }
{
  "jsonrpc": "2.0",
  "method": "graph.load",
  "params": { "name": "research-pipeline" },
  "id": 1
}

graph.list

List all saved named graph definitions. Returns the name, creation timestamp, and node count for each entry.
PropertyValue
Scoperpc
ParametersNone
Returns{ graphs: Array<{ name: string, createdAt: number, nodeCount: number }> }

graph.delete

Delete a saved named graph definition. This only removes the saved definition — it does not affect any in-progress executions or stored run artifacts.
PropertyValue
Scoperpc
Parameters{ name: string }
Returns{ name: string, deleted: true }

graph.deleteRun

PropertyValue
Scoperpc
Parameters{ runId: string }
ReturnsDeletion confirmation

graph.runDetail

PropertyValue
Scoperpc
Parameters{ runId: string }
ReturnsDetailed run info with per-node state, outputs, and timing

graph.runs

PropertyValue
Scoperpc
Parameters{ limit?: number }
Returns{ runs: object[] } — recent graph execution history
{
  "jsonrpc": "2.0",
  "method": "graph.runs",
  "params": { "limit": 5 },
  "id": 1
}
Per-agent heartbeat management for automated check-in and health monitoring.
MethodScopeDescription
heartbeat.statesadminGet all agent heartbeat states (enabled, interval, errors, backoff)
heartbeat.getadminGet heartbeat config for a specific agent
heartbeat.updateadminUpdate heartbeat configuration with persistence
heartbeat.triggeradminTrigger an immediate heartbeat run for an agent

heartbeat.states

PropertyValue
Scopeadmin
ParametersNone
Returns{ agents: Array<{ agentId, enabled, intervalMs, lastRunMs, nextDueMs, consecutiveErrors, backoffUntilMs, lastErrorKind }> }

heartbeat.get

PropertyValue
Scopeadmin
Parameters{ agentId: string } (required)
Returns{ agentId: string, perAgent: object, effective: object }

heartbeat.update

PropertyValue
Scopeadmin
Parameters{ agentId: string, enabled?: boolean, intervalMs?: number, prompt?: string, model?: string, showOk?: boolean, showAlerts?: boolean, ... }
Returns{ agentId: string, config: object, updated: true }
Updates are deep-merged with existing configuration and persisted to the YAML config file.

heartbeat.trigger

PropertyValue
Scopeadmin
Parameters{ agentId: string } (required)
Returns{ agentId: string, triggered: true }
{
  "jsonrpc": "2.0",
  "method": "heartbeat.states",
  "id": 1
}
LCD lossless-store RPCs. Both methods are rpc-scoped and back the dashboard’s Context DAG browser.
MethodScopeDescription
context.conversationsrpcList the calling agent’s distinct LCD conversations (paginated)
context.treerpcGet a conversation’s resolved DAG (summary nodes + raw-message count)
The rpc-scoped browse methods are AGENT+TENANT scoped: the calling agent comes from the request context and the tenant from the daemon — neither is a caller-supplied parameter, so a browse can never read another agent’s (or tenant’s) conversations.The in-session context tools an agent uses while running — ctx_search, ctx_inspect, ctx_expand (deep recall via ctx_recall) — are agent tools invoked through the executor, not gateway RPC methods, and are documented under the agent tool reference rather than here.Two further operator-browse RPCs the Context DAG browser will use — context.inspect (per-node metadata + taint-wrapped content recovery) and context.searchByConversation (full-text search within one conversation) — are not yet registered; calling them returns JSON-RPC -32601 (method not found). The browser degrades to loading and rendering the DAG structure without per-node deep-inspect or in-conversation search until they ship.The explicit conversation reset command is session.reset_conversation (admin-scoped), documented in the sessions accordion below.

context.conversations

PropertyValue
Scoperpc
Parameters{ limit?: number, offset?: number } (defaults: limit 100, offset 0; the agent + tenant are resolved from the request context)
Returns{ conversations: Array<{ conversation_id, tenant_id, agent_id, session_key, title, created_at, updated_at, message_count }>, total }title is always null (the LCD store has no per-conversation title); created_at / updated_at are ISO-8601 strings derived from the conversation’s earliest / latest message

context.tree

PropertyValue
Scoperpc
Parameters{ conversation_id: string } (the agent + tenant are resolved from the request context)
Returns{ conversationId, nodes: Array<{ summaryId, kind, depth, tokenCount, contentPreview, childIds, parentIds, taint, createdAt }>, messageCount }messageCount counts raw turns not yet collapsed into a summary; contentPreview is a bounded, untrusted-origin slice surfaced for the human operator view (never re-fed to a model) and taint flags untrusted nodes
Agent workspace file and git management. Read, write, and delete workspace files, browse directories, and manage git history.
MethodScopeDescription
workspace.statusrpcGet workspace status and file list
workspace.readFilerpcRead a workspace file’s content
workspace.writeFileadminCreate or overwrite a workspace file
workspace.deleteFileadminDelete a workspace file
workspace.listDirrpcList directory contents
workspace.resetFileadminReset a template file to its default content
workspace.initadminInitialize or re-bootstrap a workspace
workspace.git.statusrpcGet git working tree status
workspace.git.logrpcGet recent commit history
workspace.git.diffrpcGet unified diff of changes
workspace.git.commitadminCommit staged or all changes
workspace.git.restoreadminDiscard changes to a file

workspace.status

PropertyValue
Scoperpc
Parameters{ agentId: string }
Returns{ dir: string, exists: boolean, files: string[], hasGitRepo: boolean, isBootstrapped: boolean }
{
  "jsonrpc": "2.0",
  "method": "workspace.status",
  "params": { "agentId": "my-agent" },
  "id": 1
}

workspace.readFile

PropertyValue
Scoperpc
Parameters{ agentId: string, filePath: string }
Returns{ content: string, sizeBytes: number }
{
  "jsonrpc": "2.0",
  "method": "workspace.readFile",
  "params": { "agentId": "my-agent", "filePath": "SOUL.md" },
  "id": 1
}

workspace.writeFile

PropertyValue
Scopeadmin
Parameters{ agentId: string, filePath: string, content: string }
Returns{ written: true, sizeBytes: number }
{
  "jsonrpc": "2.0",
  "method": "workspace.writeFile",
  "params": {
    "agentId": "my-agent",
    "filePath": "IDENTITY.md",
    "content": "# Identity\n\nYou are Aria, a research assistant."
  },
  "id": 1
}

workspace.deleteFile

PropertyValue
Scopeadmin
Parameters{ agentId: string, filePath: string }
Returns{ deleted: true }

workspace.listDir

PropertyValue
Scoperpc
Parameters{ agentId: string, subdir?: string }
Returns{ entries: Array<{ name: string, type: "file" | "directory", sizeBytes?: number, modifiedAt: string }> }

workspace.resetFile

PropertyValue
Scopeadmin
Parameters{ agentId: string, fileName: string }
Returns{ reset: true, fileName: string }

workspace.init

PropertyValue
Scopeadmin
Parameters{ agentId: string }
Returns{ initialized: true, dir: string }

workspace.git.status

PropertyValue
Scoperpc
Parameters{ agentId: string }
Returns{ branch: string, clean: boolean, entries: Array<{ path: string, status: string }> }
{
  "jsonrpc": "2.0",
  "method": "workspace.git.status",
  "params": { "agentId": "my-agent" },
  "id": 1
}

workspace.git.log

PropertyValue
Scoperpc
Parameters{ agentId: string, limit?: number }
Returns{ commits: Array<{ sha: string, author: string, date: string, message: string }> }

workspace.git.diff

PropertyValue
Scoperpc
Parameters{ agentId: string, filePath?: string }
Returns{ diff: string }
{
  "jsonrpc": "2.0",
  "method": "workspace.git.diff",
  "params": { "agentId": "my-agent", "filePath": "SOUL.md" },
  "id": 1
}

workspace.git.commit

PropertyValue
Scopeadmin
Parameters{ agentId: string, message?: string, paths?: string[] }
Returns{ sha: string, author: string, date: string, message: string }
{
  "jsonrpc": "2.0",
  "method": "workspace.git.commit",
  "params": {
    "agentId": "my-agent",
    "message": "Update agent personality"
  },
  "id": 1
}

workspace.git.restore

PropertyValue
Scopeadmin
Parameters{ agentId: string, filePath: string }
Returns{ restored: true }
Write operations (writeFile, deleteFile, resetFile, init, git.commit, git.restore) require admin scope. Read operations (status, readFile, listDir, git.status, git.log, git.diff) require only rpc scope.
Runtime daemon management.
MethodScopeDescription
daemon.setLogLeveladminChange the daemon’s log level at runtime

daemon.setLogLevel

PropertyValue
Scopeadmin
Parameters{ level: string } — valid values: "trace", "debug", "info", "warn", "error", "fatal"
Returns{ updated: true, level: string }
{
  "jsonrpc": "2.0",
  "method": "daemon.setLogLevel",
  "params": { "level": "debug" },
  "id": 1
}
Discord platform action dispatch. Sends a platform-specific action to the Discord channel adapter.
MethodScopeDescription
discord.actionadminDispatch a Discord platform action (e.g., set status, manage roles)

discord.action

PropertyValue
Scopeadmin
Parameters{ action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Discord channel docs for available actions.
ReturnsPlatform-specific result object
{
  "jsonrpc": "2.0",
  "method": "discord.action",
  "params": {
    "action": "set_status",
    "status": "online",
    "activity": "Monitoring channels"
  },
  "id": 1
}
Media processing test methods and provider inspection. All methods require admin scope. Use these to verify STT, TTS, vision, document extraction, video analysis, and link processing configurations.
MethodScopeDescription
media.test.sttadminTest speech-to-text transcription
media.test.ttsadminTest text-to-speech synthesis
media.test.visionadminTest image analysis
media.test.documentadminTest document text extraction
media.test.videoadminTest video analysis
media.test.linkadminTest link content processing
media.providersadminList configured media provider capabilities

media.test.stt

PropertyValue
Scopeadmin
Parameters{ audio?: string, language?: string }audio is base64-encoded audio data
ReturnsTranscription result with text and metadata
{
  "jsonrpc": "2.0",
  "method": "media.test.stt",
  "params": { "audio": "T2dnUwACAAAAAAA...", "language": "en" },
  "id": 1
}

media.test.tts

PropertyValue
Scopeadmin
Parameters{ text: string, voice?: string, provider?: string }
ReturnsAudio result with base64-encoded audio data
{
  "jsonrpc": "2.0",
  "method": "media.test.tts",
  "params": { "text": "Hello world", "voice": "alloy" },
  "id": 1
}

media.test.vision

PropertyValue
Scopeadmin
Parameters{ image?: string, url?: string } — provide either base64 image data or a URL
ReturnsAnalysis result with description

media.test.document

PropertyValue
Scopeadmin
Parameters{ file_path: string }
ReturnsExtracted text content from the document

media.test.video

PropertyValue
Scopeadmin
Parameters{ url?: string }
ReturnsVideo analysis result
PropertyValue
Scopeadmin
Parameters{ url: string }
ReturnsProcessed link content (article extraction, metadata)

media.providers

PropertyValue
Scopeadmin
ParametersNone
Returns{ providers: object } — configured media capabilities per provider
{
  "jsonrpc": "2.0",
  "method": "media.providers",
  "id": 1
}
Cross-channel message operations: send, reply, edit, delete, fetch, react, and attach files. All methods require admin scope and a channel_type + channel_id to identify the target channel.
MethodScopeDescription
message.sendadminSend a message to a channel
message.replyadminReply to a specific message
message.editadminEdit an existing message
message.deleteadminDelete a message
message.fetchadminFetch recent messages from a channel
message.reactadminAdd a reaction to a message
message.attachadminSend a file attachment to a channel

message.send

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, text: string, buttons?: object[], cards?: object[], effects?: object[], thread_reply?: string }
Returns{ messageId: string, channelId: string }
{
  "jsonrpc": "2.0",
  "method": "message.send",
  "params": {
    "channel_type": "telegram",
    "channel_id": "chat123",
    "text": "Hello from the API!"
  },
  "id": 1
}

message.reply

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, text: string, message_id: string }
Returns{ messageId: string, channelId: string }

message.edit

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, message_id: string, text: string }
ReturnsEdit confirmation

message.delete

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, message_id: string }
ReturnsDelete confirmation

message.fetch

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, limit?: number, before?: string }
Returns{ messages: object[] }
{
  "jsonrpc": "2.0",
  "method": "message.fetch",
  "params": {
    "channel_type": "discord",
    "channel_id": "channel789",
    "limit": 10
  },
  "id": 1
}

message.react

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, message_id: string, emoji: string }
ReturnsReact confirmation

message.attach

PropertyValue
Scopeadmin
Parameters{ channel_type: string, channel_id: string, file_path: string, caption?: string }
Returns{ messageId: string, channelId: string }
Send notifications through configured channels.
MethodScopeDescription
notification.sendrpcSend a notification message

notification.send

PropertyValue
Scoperpc
Parameters{ message: string, priority?: string, channel_type?: string, channel_id?: string }
Returns{ success: boolean, entryId?: string }
{
  "jsonrpc": "2.0",
  "method": "notification.send",
  "params": {
    "message": "Build completed successfully",
    "priority": "normal"
  },
  "id": 1
}
Slack platform action dispatch. Sends a platform-specific action to the Slack channel adapter.
MethodScopeDescription
slack.actionadminDispatch a Slack platform action

slack.action

PropertyValue
Scopeadmin
Parameters{ action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Slack channel docs for available actions.
ReturnsPlatform-specific result object
{
  "jsonrpc": "2.0",
  "method": "slack.action",
  "params": {
    "action": "set_topic",
    "channel": "C0123456",
    "topic": "Sprint 42 updates"
  },
  "id": 1
}
Sub-agent lifecycle management: list running sub-agents, kill stuck executions, and steer active sub-agents with new instructions.
MethodScopeDescription
subagent.listadminList recent sub-agent runs
subagent.killadminKill a running sub-agent
subagent.steeradminInject a steering message into a running sub-agent

subagent.list

PropertyValue
Scopeadmin
Parameters{ recentMinutes?: number }
Returns{ runs: object[], total: number }
{
  "jsonrpc": "2.0",
  "method": "subagent.list",
  "params": { "recentMinutes": 30 },
  "id": 1
}

subagent.kill

PropertyValue
Scopeadmin
Parameters{ target: string } — the runId of the sub-agent to kill
Returns{ killed: true, runId: string }
{
  "jsonrpc": "2.0",
  "method": "subagent.kill",
  "params": { "target": "run_abc" },
  "id": 1
}

subagent.steer

PropertyValue
Scopeadmin
Parameters{ target: string, message: string } — inject a user-turn message into the sub-agent’s conversation
ReturnsSteer confirmation
Telegram platform action dispatch. Sends a platform-specific action to the Telegram channel adapter.
MethodScopeDescription
telegram.actionadminDispatch a Telegram platform action

telegram.action

PropertyValue
Scopeadmin
Parameters{ action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Telegram channel docs for available actions.
ReturnsPlatform-specific result object
{
  "jsonrpc": "2.0",
  "method": "telegram.action",
  "params": {
    "action": "send_message",
    "chat_id": "123456",
    "text": "Hello from Telegram action"
  },
  "id": 1
}
WhatsApp platform action dispatch. Sends a platform-specific action to the WhatsApp channel adapter.
MethodScopeDescription
whatsapp.actionadminDispatch a WhatsApp platform action

whatsapp.action

PropertyValue
Scopeadmin
Parameters{ action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See WhatsApp channel docs for available actions.
ReturnsPlatform-specific result object
{
  "jsonrpc": "2.0",
  "method": "whatsapp.action",
  "params": {
    "action": "send_template",
    "to": "1234567890",
    "template": "welcome_message"
  },
  "id": 1
}
Delivery queue status inspection. Provides a live count of messages at each stage of the outbound delivery pipeline.
MethodScopeDescription
delivery.queue.statusrpcGet per-status counts from the outbound delivery queue

delivery.queue.status

Check how many messages are currently sitting at each stage of the delivery queue. Useful for diagnosing backlogs or verifying that a channel is draining correctly. Optionally filter to a specific channel type.
PropertyValue
Scoperpc
Parameters{ channel_type?: string }
Returns{ pending: number, inFlight: number, failed: number, delivered: number, expired: number }
{
  "jsonrpc": "2.0",
  "method": "delivery.queue.status",
  "params": { "channel_type": "telegram" },
  "id": 1
}
Runtime secret management. Write secrets to the encrypted store (or .env file fallback) and list configured secret names. Values are never returned by any method — only names and metadata.
MethodScopeDescription
env.setadminWrite a secret to the encrypted store (triggers daemon restart)
env.listadminList configured secret names (values never returned)

env.set

Write a secret value to the encrypted secrets store (~/.comis/secrets.db via AES-256-GCM) or the .env file fallback when no master key is configured. The daemon restarts automatically after a successful write so the new value is available to all subsystems.Rate-limited to 5 writes per minute. The value is never logged at any level.
PropertyValue
Scopeadmin
Parameters{ key: string, value: string }
Returns{ set: true, key: string, storage: "encrypted" | "envfile", restarting: true }
key must start with an uppercase letter and contain only uppercase letters, digits, and underscores (e.g. OPENAI_API_KEY). Max length: 256 characters. value max length: 8192 characters. Passing the literal string [REDACTED] is rejected to prevent session-redaction poisoning.
{
  "jsonrpc": "2.0",
  "method": "env.set",
  "params": { "key": "OPENAI_API_KEY", "value": "sk-..." },
  "id": 1
}
env.set triggers a daemon restart (SIGUSR2) approximately 200ms after returning. Your WebSocket connection will drop and reconnect. Active sessions are preserved via restart continuations.

env.list

List the names of all configured secrets. Secret values are never included in the response. Use this before calling env.set to check whether a key is already configured.Rate-limited to 30 calls per minute.
PropertyValue
Scopeadmin
Parameters{ filter?: string, limit?: number }
Returns{ secrets: Array<{ name, source: "encrypted" | "envfile", provider?, createdAt?, updatedAt?, usageCount? }>, total: number, truncated: boolean }
filter supports glob-style patterns (e.g. OPENAI_*). limit defaults to 100, max 500.
{
  "jsonrpc": "2.0",
  "method": "env.list",
  "params": { "filter": "OPENAI_*" },
  "id": 1
}
Image generation and image analysis. image.generate produces images from a text prompt; image.analyze runs vision analysis on an existing image.
MethodScopeDescription
image.generaterpcGenerate an image from a text prompt
image.analyzerpcAnalyze an image with the configured vision provider

image.generate

Generate an image from a text prompt using the configured image generation provider (OpenAI DALL-E, fal.ai, etc.). If a _callerChannelType and _callerChannelId are available (set automatically when called from an agent tool), the image is delivered directly to the channel. Otherwise it is returned as base64.Rate-limited per-agent via the imageGen.maxPerHour config value.
PropertyValue
Scoperpc
Parameters{ prompt: string, size?: string }
Returns{ success: true, delivered?: true, imageBase64?: string, mimeType: string } or { success: false, error: string }
{
  "jsonrpc": "2.0",
  "method": "image.generate",
  "params": {
    "prompt": "A serene mountain lake at dawn, photorealistic",
    "size": "1024x1024"
  },
  "id": 1
}

image.analyze

Analyze an image using the configured vision provider. Accepts an image from a file path in the agent’s workspace, a URL, a base64 data URI, or a channel attachment URL.
PropertyValue
Scoperpc
Parameters{ source: string, source_type: "file" | "url" | "base64" | "attachment", prompt?: string, mime_type?: string }
Returns{ description: string, provider: string, model: string }
prompt defaults to "Describe this image in detail" when omitted. Vision scope rules configured under media.vision.scopeRules may deny analysis for certain channel contexts.
{
  "jsonrpc": "2.0",
  "method": "image.analyze",
  "params": {
    "source": "https://example.com/chart.png",
    "source_type": "url",
    "prompt": "What does this chart show?"
  },
  "id": 1
}
Text-to-speech synthesis and auto-trigger checking. Requires a TTS provider configured under media.tts.
MethodScopeDescription
tts.synthesizerpcSynthesize speech from text and save to the agent’s workspace
tts.auto_checkrpcCheck whether TTS should auto-trigger for a given response

tts.synthesize

Convert text to speech using the configured TTS provider. The audio file is written to the agent’s workspace under media/tts/ and the file path is returned. Old files are cleaned up automatically after one hour.Supports inline TTS directives in the text (e.g. [[tts:voice=nova]]) which override the default voice. Output format is resolved automatically based on the calling channel (Opus for Telegram, MP3 otherwise).
PropertyValue
Scoperpc
Parameters{ text: string, voice?: string, format?: string }
Returns{ filePath: string, mimeType: string, sizeBytes: number }
{
  "jsonrpc": "2.0",
  "method": "tts.synthesize",
  "params": {
    "text": "Good morning! Here is your daily briefing.",
    "voice": "nova"
  },
  "id": 1
}

tts.auto_check

Check whether TTS synthesis should be triggered automatically for a given response, based on the configured tts.autoMode setting and the presence of inbound audio or media. Used internally by the agent pipeline; exposed here for testing and custom integrations.
PropertyValue
Scoperpc
Parameters{ response_text: string, has_inbound_audio?: boolean, has_media_url?: boolean }
Returns{ shouldSynthesize: boolean, strippedText: string, mode: string }
strippedText has any [[tts:...]] directives removed. mode reflects the configured autoMode ("always", "never", "voice_reply", etc.).
On-demand media processing for agent tools: transcribe audio attachments, describe video attachments, and extract text from document attachments. These methods operate on channel attachment URLs resolved at call time, unlike the media.test.* admin methods which accept raw base64 input.
MethodScopeDescription
media.transcriberpcTranscribe an audio attachment by URL
media.describe_videorpcDescribe a video attachment by URL
media.extract_documentrpcExtract text from a document attachment by URL

media.transcribe

Transcribe an audio attachment using the configured STT provider. The attachment URL is resolved by the daemon’s attachment resolver (fetches from channel storage), then passed to the transcriber. MIME type is auto-detected from magic bytes.
PropertyValue
Scoperpc
Parameters{ attachment_url: string, language?: string }
Returns{ text: string, language?: string, durationMs?: number }
{
  "jsonrpc": "2.0",
  "method": "media.transcribe",
  "params": { "attachment_url": "https://cdn.example.com/voice/msg_001.ogg" },
  "id": 1
}

media.describe_video

Analyze a video attachment using a vision provider that supports video (e.g. Gemini). Returns a natural-language description.
PropertyValue
Scoperpc
Parameters{ attachment_url: string, prompt?: string }
Returns{ description: string, provider: string, model: string }
prompt defaults to "Describe this video concisely." when omitted. Returns an error if no video-capable vision provider is configured.

media.extract_document

Extract the text content from a document attachment (PDF, DOCX, etc.) using the configured document extraction service.
PropertyValue
Scoperpc
Parameters{ attachment_url: string }
Returns{ text: string, fileName?: string, mimeType: string, extractedChars: number, truncated: boolean, durationMs: number }
truncated is true when the document exceeded the extractor’s character limit and the text was cut off.
{
  "jsonrpc": "2.0",
  "method": "media.extract_document",
  "params": { "attachment_url": "https://cdn.example.com/docs/report.pdf" },
  "id": 1
}
Internal scheduler wake signal. Used by webhooks and other triggers to nudge the heartbeat coalescer into running immediately.
MethodScopeDescription
scheduler.wakerpcRequest an immediate heartbeat coalescer run

scheduler.wake

Signal the wake coalescer to fire immediately rather than waiting for the next scheduled interval. The coalescer debounces rapid wake calls, so multiple calls within a short window are collapsed into a single run. Returns immediately — the actual heartbeat execution is fire-and-forget.
PropertyValue
Scoperpc
Parameters{ source?: string }
Returns{ woke: true, source: string }
source is a free-form label for tracing (e.g. "webhook", "agent"). Defaults to "agent" when omitted.
{
  "jsonrpc": "2.0",
  "method": "scheduler.wake",
  "params": { "source": "webhook" },
  "id": 1
}

Error Handling

When a method call fails, the server returns a JSON-RPC error response.
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32603,
    "message": "Insufficient scope: requires 'admin'"
  },
  "id": 1
}
Common error conditions:
ErrorCodeCause
Insufficient scope-32603Token does not have the required scope for the method
Method not found-32601Unknown method name
Invalid params-32602Missing required parameters
Internal error-32603Handler threw an exception
See the WebSocket Protocol error codes table for transport-level errors (parse error, rate limiting, message size).

WebSocket Protocol

Transport protocol, error codes, and connection management

HTTP Gateway

HTTP endpoint reference and authentication

CLI Reference

CLI commands that use these JSON-RPC methods

Config YAML

Gateway and scope configuration