/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.Connect with a bearer token
4001.Verify liveness
system.ping is the cheapest method and a good way to validate auth + transport before sending real work.{"jsonrpc":"2.0","result":{"pong":true,"ts":1773313498000},"id":1}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.response, tokensUsed, and finishReason.Inspect or list the session
session.list enumerates active sessions; session.history reads the full message log for one session.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 ingateway.tokens[] with a scopes array.
| Scope | Access Level | Description |
|---|---|---|
rpc | Standard | Client operations: agent execution, memory search, cron management, browser, skills, graphs |
admin | Administrative | Config, agent management, memory management, observability, tokens, channels |
* | Wildcard | Access to all methods (both rpc and admin) |
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.params object is optional and defaults to {} when omitted. The id field correlates requests with responses.
Methods by Namespace
system (1 method)
system (1 method)
| Method | Scope | Description |
|---|---|---|
system.ping | rpc | Returns a pong response with server timestamp |
system.ping
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { pong: true, ts: number } |
agent (4 methods)
agent (4 methods)
| Method | Scope | Description |
|---|---|---|
agent.cacheStats | admin | Get prompt cache statistics for an agent |
agent.execute | rpc | Execute an agent turn (non-streaming) |
agent.stream | rpc | Execute an agent turn with streaming token deltas |
agent.getOperationModels | admin | Show how each agent operation resolves to a concrete model |
agent.cacheStats
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId?: string } |
| Returns | Cache statistics object with hit/miss rates and cache sizes |
agent.execute
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { message: string, agentId?: string, sessionKey?: object, scopes?: string[] } |
| Returns | { response: string, tokensUsed: { input, output, total }, finishReason: string } |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } |
| Returns | { agentId, primaryModel, providerFamily, tieringActive, operations: Array<{ operationType, model, provider, source, tieringActive, timeoutMs, crossProvider, apiKeyConfigured }> } |
config (10 methods)
config (10 methods)
| Method | Scope | Description |
|---|---|---|
config.apply | admin | Apply full config object |
config.diff | admin | Get unified diff between config versions |
config.gc | admin | Run config garbage collection |
config.get | admin | Read a config section (core method) |
config.history | admin | Get git-backed config change history |
config.patch | admin | Patch config value with persistence |
config.read | admin | Read config with section filtering and secret redaction |
config.rollback | admin | Rollback config to a previous version |
config.schema | admin | Get JSON Schema for config sections |
config.set | admin | Write 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { section?: string } |
| Returns | Section object (if section specified) or { config: {...}, sections: string[] } |
config.schema
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { section?: string } |
| Returns | { schema: object, sections: string[], section?: string } |
config.patch
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | Patch object (deep-merged with current config) |
| Returns | Updated config acknowledgment |
config.apply
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | Full config object to apply |
| Returns | Applied config acknowledgment |
config.diff
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { sha?: string } — compare against a specific config version |
| Returns | { diff: string } — unified diff of config changes |
config.gc
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | Garbage collection result |
config.history
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { limit?: number } |
| Returns | { entries: object[] } — git-backed config change history |
config.rollback
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { sha: string } — the version SHA to rollback to |
| Returns | Rollback 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { section?: string } |
| Returns | Record<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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { section: string, key: string, value: unknown } |
| Returns | { ok: true, previous?: unknown } |
gateway (2 methods)
gateway (2 methods)
| Method | Scope | Description |
|---|---|---|
gateway.restart | admin | Restart the gateway server |
gateway.status | admin | Process info: PID, uptime, memory, Node.js version, config paths |
gateway.restart
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | Restart confirmation |
gateway.status
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { pid: number, uptime: number, memoryUsage: number, nodeVersion: string, configPaths: string[], sections: string[] } |
obs (16 methods)
obs (16 methods)
admin scope.| Method | Scope | Description |
|---|---|---|
obs.billing.byAgent | admin | Token usage for a specific agent |
obs.billing.byProvider | admin | Token usage breakdown by LLM provider |
obs.billing.bySession | admin | Token usage for a specific session |
obs.billing.total | admin | Total billing estimate |
obs.billing.usage24h | admin | Last 24 hours usage summary |
obs.channels.all | admin | Activity data for all channels |
obs.channels.get | admin | Activity data for a single channel |
obs.channels.stale | admin | Channels with no recent activity |
obs.context.dag | admin | Get DAG state snapshot for an agent |
obs.context.pipeline | admin | Get context pipeline state for an agent |
obs.delivery.recent | admin | Recent message delivery traces |
obs.delivery.stats | admin | Aggregate delivery statistics |
obs.diagnostics | admin | Recent diagnostic events with category counts |
obs.getCacheStats | admin | Get prompt cache statistics |
obs.reset | admin | Reset all observability data (metrics, billing, delivery, channel snapshots) |
obs.reset.table | admin | Reset a specific observability table |
obs.diagnostics
| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { sinceMs?: number } |
| Returns | { totalCost: number, totalTokens: number, callCount: number, totalCacheSaved: number } |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | Array<{ hour: number, tokens: number }> |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { sinceMs?: number } |
| Returns | { providers: Array<{ provider: string, inputTokens: number, outputTokens: number, estimatedCostUsd: number }> } |
obs.billing.byAgent
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, sinceMs?: number } (agentId required) |
| Returns | { totalCost: number, totalTokens: number, callCount: number, totalCacheSaved: number } |
obs.billing.bySession
| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { channels: Array<{ channelId, channelType, lastActiveAt, messagesSent, messagesReceived }> } |
obs.channels.stale
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { thresholdMs?: number } (default: 300000 / 5 minutes) |
| Returns | { stale: ChannelActivity[] } |
obs.channels.get
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channelId: string } (required) |
| Returns | { channel: ChannelActivity | null } |
obs.delivery.recent
| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { total: number, successes: number, failures: number, avgLatencyMs: number } |
obs.context.dag
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId?: string } |
| Returns | DAG state snapshot with node counts, depths, and compaction history |
obs.context.pipeline
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId?: string } |
| Returns | Context pipeline state including layer configuration and token budgets |
obs.getCacheStats
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | Prompt cache statistics with hit/miss rates, savings estimates, and per-provider breakdowns |
obs.trace.search
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.| Property | Value |
|---|---|
| Scope | admin |
| 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. |
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).| Property | Value |
|---|---|
| Scope | admin |
| 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. |
| Returns | An 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? } |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { sinceHours?: number } — the aggregation window in hours (positive). Optional; defaults to 24 in the handler. |
| Returns | A 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? } |
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
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { reset: true, rowsDeleted: { tokenUsage: number, delivery: number, diagnostics: number, channels: number } } |
obs.reset.table
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { table: string } — valid values: "token_usage", "delivery", "diagnostics", "channels" |
| Returns | { reset: true, table: string, rowsDeleted: number } |
session (11 methods)
session (11 methods)
rpc scope; administrative operations use admin scope.| Method | Scope | Description |
|---|---|---|
session.send | rpc | Send a message to an existing session |
session.spawn | rpc | Spawn a sub-agent session |
session.status | rpc | Get session status |
session.history | rpc | Get session conversation history |
session.search | rpc | Search session content by query |
session.run_status | rpc | Get live status of a specific sub-agent run |
session.list | admin | List all active sessions |
session.delete | admin | Delete a session |
session.reset | admin | Reset all sessions |
session.export | admin | Export session data |
session.compact | admin | Compact session history |
session.reset_conversation | admin | Complete 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None (resolved from the calling agent context) |
| Returns | { model: string, agentName: string, tokensUsed: { totalTokens, totalCost }, stepsExecuted: number, maxSteps: number } |
session.history
Retrieve the conversation history for a session. Returns the raw message array stored in the session, including both user and assistant turns.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { kind?: "all" | "sub-agent" | "group" | "dm", since_minutes?: number } |
| Returns | { sessions: Array<{ sessionKey, agentId, messageCount, updatedAt, metadata }> } |
session.send
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { key: string, message: string, agentId?: string } |
| Returns | Agent response |
session.spawn
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { parentKey: string, task: string, agentId?: string } |
| Returns | Spawned session info |
session.delete
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { session_key: string } |
| Returns | { sessionKey: string, deleted: true, transcript: object } |
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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { session_key: string } |
| Returns | { sessionKey, messages, metadata, messageCount, createdAt, updatedAt } |
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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { run_id: string } |
| Returns | { runId, status, agentId, task, sessionKey, startedAt, completedAt?, runtimeMs, response?, tokensUsed?, cost?, error? } |
session.search
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { query: string, limit?: number } |
| Returns | Array<{ sessionKey: string, agentId: string, channelType: string, snippet: string, score: number, timestamp: number }> |
session.compact
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { key: string } |
| Returns | Compaction 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.| Property | Value |
|---|---|
| Scope | admin |
| 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). |
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.cron (7 methods)
cron (7 methods)
| Method | Scope | Description |
|---|---|---|
cron.list | rpc | List all cron jobs |
cron.add | rpc | Add a new cron job |
cron.update | rpc | Update an existing cron job |
cron.remove | rpc | Remove a cron job |
cron.status | rpc | Get cron job status |
cron.runs | rpc | Get cron job run history |
cron.run | rpc | Trigger a manual cron run |
cron.add
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string, message: string, agentId?: string, schedule: { kind: "cron" | "interval" | "once", expr?: string, tz?: string, everyMs?: number, at?: string } } |
| Returns | Created job info |
cron.list
List all scheduled jobs. Returns each job’s name, schedule expression, next run time, and whether it is currently enabled.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { jobs: Array<{ id, name, scheduleKind, expr?, tz?, everyMs?, nextRunAtMs, enabled, lastRunAtMs?, lastError? }> } |
cron.update
Update an existing cron job’s schedule or message. Only the fields you provide are changed.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string, message?: string, agentId?: string, schedule?: { kind: "cron" | "interval" | "once", expr?: string, tz?: string, everyMs?: number, at?: string } } |
| Returns | Updated job info |
cron.status
Get the current status of a single cron job by name.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string, limit?: number } |
| Returns | { runs: Array<{ runAt: number, durationMs: number, success: boolean, error?: string }> } |
cron.remove
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string } |
| Returns | Removal 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name?: string, mode?: "force" | "due" } (name required when mode is "force") |
| Returns | { triggered: true, mode: string, jobName?: string } |
browser (13 methods)
browser (13 methods)
rpc scope and bridge to the browser automation subsystem.| Method | Scope | Description |
|---|---|---|
browser.status | rpc | Browser session status (running, URL, tab count) |
browser.start | rpc | Start a browser session |
browser.stop | rpc | Stop the browser session |
browser.navigate | rpc | Navigate to a URL |
browser.snapshot | rpc | Take a DOM snapshot (accessibility tree) |
browser.screenshot | rpc | Take a screenshot (returns base64 PNG) |
browser.pdf | rpc | Generate a PDF of the current page |
browser.act | rpc | Execute a browser action (click, type, scroll) |
browser.tabs | rpc | List open browser tabs |
browser.open | rpc | Open a new tab |
browser.focus | rpc | Focus a specific tab |
browser.close | rpc | Close a tab |
browser.console | rpc | Get 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { started: true } |
browser.stop
Stop the active browser session and close all tabs. Any ongoing automation is interrupted.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { stopped: true } |
browser.navigate
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { url: string } |
| Returns | Navigation result with final URL |
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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | Accessibility tree snapshot object |
browser.screenshot
| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { data: string } (base64-encoded PDF) |
browser.act
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { action: string, selector?: string, text?: string, value?: string } |
| Returns | Action result |
browser.tabs
List all currently open browser tabs with their IDs, URLs, and titles.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { tabs: Array<{ id: string, url: string, title: string }> } |
browser.open
Open a new browser tab, optionally navigating to a URL immediately.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { url?: string } |
| Returns | { tabId: string } |
browser.focus
Focus a specific tab by its ID, making it the active tab for subsequent commands.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { tabId: string } |
| Returns | { focused: true, tabId: string } |
browser.close
Close a specific tab by its ID.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | { entries: Array<{ level: string, text: string, timestamp: number }> } |
audio (1 method)
audio (1 method)
| Method | Scope | Description |
|---|---|---|
audio.transcribe | rpc | Transcribe audio to text |
audio.transcribe
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { audio: string, mimeType?: string, language?: string } (audio is base64-encoded, mimeType defaults to "audio/ogg") |
| Returns | { text: string, language?: string, durationMs?: number } |
{ error: "..." } if STT is not configured or transcription fails.admin.approval (4 methods)
admin.approval (4 methods)
| Method | Scope | Description |
|---|---|---|
admin.approval.clearDenialCache | admin | Clear the denial cache for approval gates |
admin.approval.pending | admin | List pending approval requests |
admin.approval.resolve | admin | Approve or deny a pending request |
admin.approval.resolveAll | admin | Bulk-resolve all pending approval requests for a session |
admin.approval.clearDenialCache
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { cleared: true } |
admin.approval.pending
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | {} |
| Returns | List of pending approval requests |
admin.approval.resolve
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { id: string, approved: boolean, reason?: string } |
| Returns | Resolution 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.| Property | Value |
|---|---|
| Scope | admin |
| 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.agents (7 methods)
agents (7 methods)
| Method | Scope | Description |
|---|---|---|
agents.list | admin | List all configured agents |
agents.create | admin | Create a new agent |
agents.get | admin | Get agent configuration |
agents.update | admin | Update agent configuration |
agents.delete | admin | Delete an agent |
agents.suspend | admin | Suspend an agent (stop processing) |
agents.resume | admin | Resume 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { agents: string[] } |
agents.create
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { name: string, provider?: string, model?: string, ...config } |
| Returns | Created agent configuration |
agents.get
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } |
| Returns | Agent configuration object |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, name?: string, provider?: string, model?: string, dryRun?: boolean, ...config } |
| Returns | Updated agent configuration (or, with dryRun: true, the validation outcome with no side effects) |
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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } |
| Returns | { agentId: string, suspended: true } |
agents.resume
Resume a previously suspended agent, allowing it to accept messages again.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } |
| Returns | { agentId: string, resumed: true } |
memory (9 methods)
memory (9 methods)
rpc scope; management methods use admin scope.| Method | Scope | Description |
|---|---|---|
memory.browse | admin | Browse memory entries with pagination |
memory.delete | admin | Delete a memory entry |
memory.embeddingCache | admin | Get embedding cache statistics |
memory.export | admin | Export memory database |
memory.flush | admin | Flush all memory entries |
memory.inspect | rpc | Inspect memory entry or statistics |
memory.search | rpc | Search memory entries (full-text + vector) |
memory.stats | admin | Memory system statistics |
memory.store | admin | Store a new memory entry |
memory.search
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { query: string, limit?: number } |
| Returns | { results: MemoryEntry[] } |
memory.browse
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { offset?: number, limit?: number } |
| Returns | Paginated memory entries |
memory.delete
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { id: string } |
| Returns | Deletion confirmation |
memory.embeddingCache
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | Cache 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { id?: string, tenantId?: string } |
| Returns | { entry?: MemoryEntry } (with id) or { stats?: object } (without id) |
memory.stats
Get aggregate statistics for the memory system: total entry count, database size, embedding cache hit rate, and provider information.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { flushed: true, deletedCount: number } |
memory.export
Export the entire memory database as a portable JSON snapshot. Useful for backups, migration between instances, or offline analysis.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { entries: MemoryEntry[], exportedAt: number, totalEntries: number } |
memory.store
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { content: string, metadata?: object } |
| Returns | Stored entry ID |
models (3 methods)
models (3 methods)
@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.| Method | Scope | Description |
|---|---|---|
models.list_providers | admin | List all providers known to the pi-ai catalog |
models.list | admin | List available models from the catalog (optionally filtered to one provider) |
models.test | admin | Test 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).| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { providers: string[], count: number } |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { provider?: string } (omit for all providers) |
| Returns | Array<{ provider, modelId, displayName, contextWindow, maxTokens, baseUrl, input, reasoning, cost: { input, output, cacheRead, cacheWrite }, validated, validatedAt }> |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { model: string, provider?: string } |
| Returns | { ok: boolean, latencyMs: number, provider: string, error?: string } |
tokens (4 methods)
tokens (4 methods)
| Method | Scope | Description |
|---|---|---|
tokens.list | admin | List all gateway tokens (secrets redacted) |
tokens.create | admin | Create a new gateway token |
tokens.revoke | admin | Revoke a gateway token |
tokens.rotate | admin | Rotate 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { tokens: Array<{ id: string, scopes: string[], createdAt: string }> } |
tokens.create
Create a new gateway token. The secret is returned only in this response — it cannot be retrieved again. Store it securely immediately.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { id: string } |
| Returns | { id: string, secret: string, scopes: string[], rotated: true } |
channels (7 methods)
channels (7 methods)
| Method | Scope | Description |
|---|---|---|
channels.capabilities | rpc | Get per-channel capability matrix |
channels.disable | admin | Disable a channel adapter |
channels.enable | admin | Enable a channel adapter |
channels.get | admin | Get detailed channel information |
channels.health | rpc | Get channel health summary |
channels.list | admin | List all configured channels with status |
channels.restart | admin | Restart 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { channels: Array<{ channelType, channelId?, status: "running" | "stopped" }>, total: number } |
channels.capabilities
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { channel_type: string } |
| Returns | { channelType: string, features: object } — the feature capability map for the specified channel type |
channels.get
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string } |
| Returns | { channelType, channelId?, status: "running" | "stopped", configured?: boolean } |
channels.health
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| Returns | Channel health summary with connectivity status |
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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string } |
| Returns | { channelType: string, status: "stopped", message: string } |
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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string } |
| Returns | { channelType: string, status: "running", message: string } |
mcp (6 methods)
mcp (6 methods)
| Method | Scope | Description |
|---|---|---|
mcp.list | admin | List all configured MCP servers |
mcp.status | admin | Get MCP server connection status |
mcp.connect | admin | Connect to an MCP server |
mcp.disconnect | admin | Disconnect from an MCP server |
mcp.reconnect | admin | Reconnect to an MCP server |
mcp.test | admin | Test MCP server connectivity |
mcp.list
List all configured MCP servers with their current connection status and tool counts.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { serverId: string } |
| Returns | Connection 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.| Property | Value |
|---|---|
| Scope | admin |
| 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { serverId: string } |
| Returns | Reconnection 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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { serverId: string } |
| Returns | { serverId: string, ok: boolean, latencyMs: number, error?: string } |
skills (6 methods)
skills (6 methods)
| Method | Scope | Description |
|---|---|---|
skills.list | rpc | List prompt skills for an agent |
skills.create | admin | Create a new skill from SKILL.md content (single-file shortcut) |
skills.upload | admin | Upload a skill folder (files + SKILL.md) |
skills.import | admin | Import a skill from a GitHub repository URL |
skills.update | admin | Update an existing skill’s SKILL.md content |
skills.delete | admin | Delete a skill |
skills.list
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId?: string } |
| Returns | { skills: SkillDescription[] } |
skills.upload
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { name: string, agentId?: string, scope?: "local" | "shared", files: Array<{ path: string, content: string }> } |
| Returns | { ok: true, path: string } |
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".skills.import
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { url: string, agentId?: string, scope?: "local" | "shared" } |
| Returns | { ok: true, path: string, name: string, fileCount: number } |
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.| Property | Value |
|---|---|
| Scope | admin |
| 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.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.| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { name: string, content: string, agentId?: string, scope?: "local" | "shared" } |
| Returns | { ok: true, path: string, name: string } |
skills.delete
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { name: string, agentId?: string, scope?: "local" | "shared" } |
| Returns | { ok: true } |
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 (12 methods)
graph (12 methods)
| Method | Scope | Description |
|---|---|---|
graph.cancel | rpc | Cancel a running graph execution |
graph.define | rpc | Define an execution graph |
graph.delete | rpc | Delete a saved graph definition |
graph.deleteRun | rpc | Delete a graph execution run and its artifacts |
graph.execute | rpc | Execute a defined graph |
graph.list | rpc | List saved graph definitions |
graph.load | rpc | Load a named graph definition |
graph.outputs | rpc | Retrieve node output values from a graph |
graph.runDetail | rpc | Get detailed info for a specific execution run |
graph.runs | rpc | List recent graph execution runs |
graph.save | rpc | Save a named graph definition |
graph.status | rpc | Get graph execution status |
graph.define
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { nodes: NodeDefinition[], edges: EdgeDefinition[] } |
| Returns | { graphId: string } |
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.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 Type | Description |
|---|---|
typed_node_agentid_ignored | agentId set on a typed node is ignored — agents come from type_config |
typed_node_expensive_retry | retries > 0 on a typed node re-runs the entire driver from scratch |
typed_node_approval_retry | Retries on an approval-gate node will re-prompt the user |
graph.execute
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { graphId: string, inputs?: Record<string, unknown> } |
| Returns | Execution result with per-node outputs |
approval-gate nodes, the request must include announceChannelType and announceChannelId for user interaction routing.graph.status
Returns graph execution status. This method has two response forms depending on whether a graphId parameter is provided.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { graphId?: string, recentMinutes?: number } |
| Returns | Per-node status (with graphId) or graph list with concurrency stats (without graphId) |
graphId — Returns detailed per-node execution state for a single graph, including node outputs (truncated to 500 characters), timing, and aggregate stats.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.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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { graphId: string } |
| Returns | { graphId: string, outputs: Record<string, string | null>, source: "memory" | "disk" } |
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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string } |
| Returns | { graphId: string, name: string } |
graph.list
List all saved named graph definitions. Returns the name, creation timestamp, and node count for each entry.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | None |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { name: string } |
| Returns | { name: string, deleted: true } |
graph.deleteRun
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { runId: string } |
| Returns | Deletion confirmation |
graph.runDetail
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { runId: string } |
| Returns | Detailed run info with per-node state, outputs, and timing |
graph.runs
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { limit?: number } |
| Returns | { runs: object[] } — recent graph execution history |
heartbeat (4 methods)
heartbeat (4 methods)
| Method | Scope | Description |
|---|---|---|
heartbeat.states | admin | Get all agent heartbeat states (enabled, interval, errors, backoff) |
heartbeat.get | admin | Get heartbeat config for a specific agent |
heartbeat.update | admin | Update heartbeat configuration with persistence |
heartbeat.trigger | admin | Trigger an immediate heartbeat run for an agent |
heartbeat.states
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { agents: Array<{ agentId, enabled, intervalMs, lastRunMs, nextDueMs, consecutiveErrors, backoffUntilMs, lastErrorKind }> } |
heartbeat.get
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } (required) |
| Returns | { agentId: string, perAgent: object, effective: object } |
heartbeat.update
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, enabled?: boolean, intervalMs?: number, prompt?: string, model?: string, showOk?: boolean, showAlerts?: boolean, ... } |
| Returns | { agentId: string, config: object, updated: true } |
heartbeat.trigger
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } (required) |
| Returns | { agentId: string, triggered: true } |
context (2 methods)
context (2 methods)
rpc-scoped and back the dashboard’s Context DAG browser.| Method | Scope | Description |
|---|---|---|
context.conversations | rpc | List the calling agent’s distinct LCD conversations (paginated) |
context.tree | rpc | Get a conversation’s resolved DAG (summary nodes + raw-message count) |
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
| Property | Value |
|---|---|
| Scope | rpc |
| 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
| Property | Value |
|---|---|
| Scope | rpc |
| 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 |
workspace (12 methods)
workspace (12 methods)
| Method | Scope | Description |
|---|---|---|
workspace.status | rpc | Get workspace status and file list |
workspace.readFile | rpc | Read a workspace file’s content |
workspace.writeFile | admin | Create or overwrite a workspace file |
workspace.deleteFile | admin | Delete a workspace file |
workspace.listDir | rpc | List directory contents |
workspace.resetFile | admin | Reset a template file to its default content |
workspace.init | admin | Initialize or re-bootstrap a workspace |
workspace.git.status | rpc | Get git working tree status |
workspace.git.log | rpc | Get recent commit history |
workspace.git.diff | rpc | Get unified diff of changes |
workspace.git.commit | admin | Commit staged or all changes |
workspace.git.restore | admin | Discard changes to a file |
workspace.status
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string } |
| Returns | { dir: string, exists: boolean, files: string[], hasGitRepo: boolean, isBootstrapped: boolean } |
workspace.readFile
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string, filePath: string } |
| Returns | { content: string, sizeBytes: number } |
workspace.writeFile
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, filePath: string, content: string } |
| Returns | { written: true, sizeBytes: number } |
workspace.deleteFile
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, filePath: string } |
| Returns | { deleted: true } |
workspace.listDir
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string, subdir?: string } |
| Returns | { entries: Array<{ name: string, type: "file" | "directory", sizeBytes?: number, modifiedAt: string }> } |
workspace.resetFile
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, fileName: string } |
| Returns | { reset: true, fileName: string } |
workspace.init
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string } |
| Returns | { initialized: true, dir: string } |
workspace.git.status
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string } |
| Returns | { branch: string, clean: boolean, entries: Array<{ path: string, status: string }> } |
workspace.git.log
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string, limit?: number } |
| Returns | { commits: Array<{ sha: string, author: string, date: string, message: string }> } |
workspace.git.diff
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { agentId: string, filePath?: string } |
| Returns | { diff: string } |
workspace.git.commit
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, message?: string, paths?: string[] } |
| Returns | { sha: string, author: string, date: string, message: string } |
workspace.git.restore
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { agentId: string, filePath: string } |
| Returns | { restored: true } |
daemon (1 method)
daemon (1 method)
| Method | Scope | Description |
|---|---|---|
daemon.setLogLevel | admin | Change the daemon’s log level at runtime |
daemon.setLogLevel
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { level: string } — valid values: "trace", "debug", "info", "warn", "error", "fatal" |
| Returns | { updated: true, level: string } |
discord (1 method)
discord (1 method)
| Method | Scope | Description |
|---|---|---|
discord.action | admin | Dispatch a Discord platform action (e.g., set status, manage roles) |
discord.action
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Discord channel docs for available actions. |
| Returns | Platform-specific result object |
media (7 methods)
media (7 methods)
admin scope. Use these to verify STT, TTS, vision, document extraction, video analysis, and link processing configurations.| Method | Scope | Description |
|---|---|---|
media.test.stt | admin | Test speech-to-text transcription |
media.test.tts | admin | Test text-to-speech synthesis |
media.test.vision | admin | Test image analysis |
media.test.document | admin | Test document text extraction |
media.test.video | admin | Test video analysis |
media.test.link | admin | Test link content processing |
media.providers | admin | List configured media provider capabilities |
media.test.stt
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { audio?: string, language?: string } — audio is base64-encoded audio data |
| Returns | Transcription result with text and metadata |
media.test.tts
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { text: string, voice?: string, provider?: string } |
| Returns | Audio result with base64-encoded audio data |
media.test.vision
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { image?: string, url?: string } — provide either base64 image data or a URL |
| Returns | Analysis result with description |
media.test.document
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { file_path: string } |
| Returns | Extracted text content from the document |
media.test.video
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { url?: string } |
| Returns | Video analysis result |
media.test.link
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { url: string } |
| Returns | Processed link content (article extraction, metadata) |
media.providers
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | None |
| Returns | { providers: object } — configured media capabilities per provider |
message (7 methods)
message (7 methods)
admin scope and a channel_type + channel_id to identify the target channel.| Method | Scope | Description |
|---|---|---|
message.send | admin | Send a message to a channel |
message.reply | admin | Reply to a specific message |
message.edit | admin | Edit an existing message |
message.delete | admin | Delete a message |
message.fetch | admin | Fetch recent messages from a channel |
message.react | admin | Add a reaction to a message |
message.attach | admin | Send a file attachment to a channel |
message.send
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, text: string, buttons?: object[], cards?: object[], effects?: object[], thread_reply?: string } |
| Returns | { messageId: string, channelId: string } |
message.reply
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, text: string, message_id: string } |
| Returns | { messageId: string, channelId: string } |
message.edit
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, message_id: string, text: string } |
| Returns | Edit confirmation |
message.delete
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, message_id: string } |
| Returns | Delete confirmation |
message.fetch
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, limit?: number, before?: string } |
| Returns | { messages: object[] } |
message.react
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, message_id: string, emoji: string } |
| Returns | React confirmation |
message.attach
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { channel_type: string, channel_id: string, file_path: string, caption?: string } |
| Returns | { messageId: string, channelId: string } |
notification (1 method)
notification (1 method)
| Method | Scope | Description |
|---|---|---|
notification.send | rpc | Send a notification message |
notification.send
| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { message: string, priority?: string, channel_type?: string, channel_id?: string } |
| Returns | { success: boolean, entryId?: string } |
slack (1 method)
slack (1 method)
| Method | Scope | Description |
|---|---|---|
slack.action | admin | Dispatch a Slack platform action |
slack.action
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Slack channel docs for available actions. |
| Returns | Platform-specific result object |
subagent (3 methods)
subagent (3 methods)
| Method | Scope | Description |
|---|---|---|
subagent.list | admin | List recent sub-agent runs |
subagent.kill | admin | Kill a running sub-agent |
subagent.steer | admin | Inject a steering message into a running sub-agent |
subagent.list
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { recentMinutes?: number } |
| Returns | { runs: object[], total: number } |
subagent.kill
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { target: string } — the runId of the sub-agent to kill |
| Returns | { killed: true, runId: string } |
subagent.steer
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { target: string, message: string } — inject a user-turn message into the sub-agent’s conversation |
| Returns | Steer confirmation |
telegram (1 method)
telegram (1 method)
| Method | Scope | Description |
|---|---|---|
telegram.action | admin | Dispatch a Telegram platform action |
telegram.action
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See Telegram channel docs for available actions. |
| Returns | Platform-specific result object |
whatsapp (1 method)
whatsapp (1 method)
| Method | Scope | Description |
|---|---|---|
whatsapp.action | admin | Dispatch a WhatsApp platform action |
whatsapp.action
| Property | Value |
|---|---|
| Scope | admin |
| Parameters | { action: string, ...platformParams } — the action string selects the operation; additional parameters vary per action. See WhatsApp channel docs for available actions. |
| Returns | Platform-specific result object |
delivery (1 method)
delivery (1 method)
| Method | Scope | Description |
|---|---|---|
delivery.queue.status | rpc | Get 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { channel_type?: string } |
| Returns | { pending: number, inFlight: number, failed: number, delivered: number, expired: number } |
env (2 methods)
env (2 methods)
.env file fallback) and list configured secret names. Values are never returned by any method — only names and metadata.| Method | Scope | Description |
|---|---|---|
env.set | admin | Write a secret to the encrypted store (triggers daemon restart) |
env.list | admin | List 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.| Property | Value |
|---|---|
| Scope | admin |
| 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.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.| Property | Value |
|---|---|
| Scope | admin |
| 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.image (2 methods)
image (2 methods)
image.generate produces images from a text prompt; image.analyze runs vision analysis on an existing image.| Method | Scope | Description |
|---|---|---|
image.generate | rpc | Generate an image from a text prompt |
image.analyze | rpc | Analyze 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { prompt: string, size?: string } |
| Returns | { success: true, delivered?: true, imageBase64?: string, mimeType: string } or { success: false, error: string } |
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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.tts (2 methods)
tts (2 methods)
media.tts.| Method | Scope | Description |
|---|---|---|
tts.synthesize | rpc | Synthesize speech from text and save to the agent’s workspace |
tts.auto_check | rpc | Check 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).| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { text: string, voice?: string, format?: string } |
| Returns | { filePath: string, mimeType: string, sizeBytes: number } |
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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.).link (1 method)
link (1 method)
| Method | Scope | Description |
|---|---|---|
link.process | rpc | Process message text through the link understanding pipeline |
link.process
Run message text through the link processing pipeline. URLs in the text are fetched, article content is extracted, and the enriched text is returned with inline summaries or expansions. Used by the agent pipeline automatically; exposed here for custom preprocessing workflows.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { text: string } |
| Returns | { enrichedText: string, linksProcessed: number, errors: string[] } |
media (3 agent-facing methods)
media (3 agent-facing methods)
media.test.* admin methods which accept raw base64 input.| Method | Scope | Description |
|---|---|---|
media.transcribe | rpc | Transcribe an audio attachment by URL |
media.describe_video | rpc | Describe a video attachment by URL |
media.extract_document | rpc | Extract 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.| Property | Value |
|---|---|
| Scope | rpc |
| Parameters | { attachment_url: string, language?: string } |
| Returns | { text: string, language?: string, durationMs?: number } |
media.describe_video
Analyze a video attachment using a vision provider that supports video (e.g. Gemini). Returns a natural-language description.| Property | Value |
|---|---|
| Scope | rpc |
| 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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.scheduler (1 method)
scheduler (1 method)
| Method | Scope | Description |
|---|---|---|
scheduler.wake | rpc | Request 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.| Property | Value |
|---|---|
| Scope | rpc |
| 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.Error Handling
When a method call fails, the server returns a JSON-RPC error response.| Error | Code | Cause |
|---|---|---|
| Insufficient scope | -32603 | Token does not have the required scope for the method |
| Method not found | -32601 | Unknown method name |
| Invalid params | -32602 | Missing required parameters |
| Internal error | -32603 | Handler threw an exception |
