MCP tool reference — gateway

Auto-generated from TOOL_DEFINITIONS in runtime/src/mcp/tools.ts — do not edit by hand.

The myai gateway exposes 189 MCP tools at http://localhost:3100/mcp. Any MCP-capable agent (Claude Code, Cursor, Windsurf, Codex CLI — see myai connect-agent) can call them. Required parameters are marked bold.

MEMORY / RAG

Search the RAG memory for relevant context. Returns semantically similar chunks from state files, handoff notes, commit messages, PR descriptions, and SONA patterns across all managed repos.

ParameterTypeDescription
querystringNatural language search query
repostringFilter to a specific repo name (optional)
sourcestate \handoff \commit \pr \pattern \bug \code \feature \archive \brainFilter by source type (optional)
tagsstring[]Filter by tags (optional)
limitnumberMax results (default 10)

recall_session

Recall past work sessions by semantic similarity. Searches the session corpus (STATE.md session blocks, handoff notes, and archived sessions) and returns the most relevant blocks ranked by similarity. Use to answer "what did we do for PR #99?", "when did we ship Phase 5b?", or "what was the fix for the update_all.sh bug?" without grepping the archive. Filter by repo or restrict to recent work with since.

ParameterTypeDescription
querystringNatural language query about past work, e.g. "the update_all.sh overlay-merge bug"
knumberNumber of session blocks to return (default 5)
sincestringISO date (YYYY-MM-DD) — only recall sessions on or after this date (optional)
repostringFilter to a specific repo name (optional)

memory_store

Store a new text chunk in the RAG memory with automatic embedding. Deduplicates by content hash.

ParameterTypeDescription
contentstringText content to embed and store
repostringRepo this content belongs to
sourcestate \handoff \commit \pr \pattern \bug \code \feature \archiveSource type
tagsstring[]Tags for filtering
sessionIdstringSession identifier

memory_context

Assemble a pre-built context block for a repo: top recent state chunks + handoff + related patterns. Returns a ready-to-inject markdown block.

ParameterTypeDescription
repostringRepo name
querystringOptional focus query to bias retrieval
limitnumberMax chunks per source (default 5)

memory_stats

Get vector count statistics by repo and source type.

ParameterTypeDescription
repostringFilter to a specific repo (optional)

memory_reindex

Re-embed and upsert vectors for STATE.md, AI_AGENT_HANDOFF.md, state/archive/.md, and brain session atoms (repos/<ns>/sessions/.md in the brain store — recent sessions that have not yet rotated into state/archive/). brain_merge already embeds touched namespaces automatically; this is the full-sweep catch-up. Idempotent via content-hash dedup (plus cross-source session-date dedup between brain and archive). Master repo only by default; pass scope=all to also index every managed repo.

ParameterTypeDescription
scopemaster \allmaster = this repo only (default), all = master + every managed repo

STATE

state_read

Read STATE.md or AI_AGENT_HANDOFF.md for a repo. Returns raw file content.

ParameterTypeDescription
repostringRepo name (reads from master repo if omitted)
filestate \handoffWhich file to read (default: state)

state_update

Replace or append a section in STATE.md or AI_AGENT_HANDOFF.md. Section is identified by a markdown heading (e.g. "## 3. Blockers"). If the heading does not exist, content is appended to the file.

ParameterTypeDescription
repostringRepo name (master repo if omitted)
filestate \handoffTarget file (default: state)
headingstringMarkdown heading that starts the section (include ##/### and text). Omit to append to end of file.
contentstringNew section body (without the heading line). Heading is preserved or appended.
modereplace \appendreplace = overwrite section body, append = add after existing body (default: replace)

TASKS

tasks_list

List tasks in the queue. Filter by repo, status, priority, or assigned agent. Sorted by priority then creation time (taskId as tiebreaker). Bounded to limit rows (default 50); when more rows exist past this page, the response carries a nextCursor — pass it back as cursor to fetch the next page. Omitting cursor always starts from the beginning, so existing callers are unaffected.

ParameterTypeDescription
repostringFilter by repo (optional)
statuspending \working \review \done \blocked \paused \dead_letterFilter by status (optional)
priorityP0 \P1 \P2 \P3Filter by priority (optional)
assignedAgentstringFilter by assigned agent (optional)
limitnumberMax results per page (default 50)
cursorstringOpaque pagination cursor from a prior response's nextCursor (optional — omit for the first page)

tasks_create

Create a new task in the queue. Returns the created task with assigned ID.

ParameterTypeDescription
repostringTarget repo name
titlestringTask title
descriptionstringTask details (optional)
priorityP0 \P1 \P2 \P3Priority (default P2)
assignedAgentstringSpecialist agent to assign (optional)
recommendedModelstringRecommended model for this task, e.g. claude-fable-5, claude-sonnet-4-6 (optional)
recommendedModelPreferencebooleantrue: recommendedModel is a demotable PREFERENCE (e.g. backlog/queue_topup auto-seeding) the runner policy may demote to the free local tier for mechanical docs/summarize/triage work. Omit/false: an absolute pin, always honored (default, unchanged behavior) — task-972913b7.
sourcemanual \connect-hub \auto-detected \scheduler \telegramWhere it originated (default: manual)
sourceIdstringExternal ref ID (e.g. bug-123)
notesstringAdditional notes (optional)
dependsOnstring[]Upstream taskIds this task waits on (DAG scheduling): tasks_claim skips the task until every upstream is status done. Upstreams must exist — unknown IDs are rejected. Use for ordered multi-step plans, e.g. migrate-DB task first, build-UI task dependsOn it.

tasks_update

Update a task by ID: re-point repo, change status, priority, assigned agent, PR URL, notes, telegram message ID. Automatically sets startedAt when moving to working, completedAt when moving to done/blocked. BULK-BLOCK GUARD: a pending→blocked transition without supersededBy or operatorAuthorized is only allowed up to a per-repo burst threshold (default 5 per 15min, see bulk-block-guard.ts) — past that it is rejected and an alert fires, so a runaway process cannot silently mass-block a repo's curated pending queue.

ParameterTypeDescription
taskIdstringTask ID to update
repostringRe-point a misfiled task to a different repo (e.g. old-name → new-name). Empty/whitespace is ignored.
statuspending \working \review \done \blocked \paused \dead_letterSetting pending on a blocked/dead_letter task replays it — clears the retry ledger for a fresh attempt chain.
priorityP0 \P1 \P2 \P3
assignedAgentstring
recommendedModelstring
recommendedModelPreferencebooleanSee tasks_create — true marks recommendedModel demotable, not an absolute pin.
prUrlstring
notesstring
telegramMessageIdnumber
routedProfilestringRouter audit trail: the capacity pool the runner actually routed this task to (e.g. claude-tech, claude-fable), stamped at claim time
routedModelstringRouter audit trail: the model the runner actually routed this task to (e.g. claude-sonnet-5, claude-opus-4-8), stamped at claim time
routedComplexitystringRouter audit trail: the route_complexity classification (trivial\standard\complex) used for this task, stamped at claim time
executionLaneclaude \agentic-fallbackWhich backend actually executed this run — the normal Claude CLI chain, or the non-Claude agentic FALLBACK lane (DeepSeek/Kimi, scripts/lib/openai_agent.py). Stamped by the runner at review close-off, once settled.
executionProviderstringVendor label for executionLane (e.g. anthropic, deepseek, kimi), stamped alongside executionLane.
workTypeagentic-interactive \agentic-autonomous \frontend \backend \docs \chat \research \code-review \architecture \database \security \data-embeddings \summarize-extractWork-type routing stamp: the declared work-type hint (plan/MULTI_PROVIDER_ORCHESTRATION.md §3) this task was routed under, stamped at claim time.
workTypeTierstringWork-type routing stamp: the primary tier WORK_TYPE_TIER_MAP resolved workType to (e.g. standard, budget, premium), stamped at claim time.
workTypeFailoverHopstringWork-type routing stamp: the documented first-hop failover for workType — a model (same-provider hop, router.ts escalateTo) or a provider (cross-provider hop, spliced into the chain) — stamped at claim time.
supersededBystringExplicit supersession record: taskId of the task that replaces this one. Authorizes a pending→blocked transition past the bulk-block guard threshold.
operatorAuthorizedbooleanExplicit human-consented authorization for a bulk block, in lieu of supersededBy. Never set true from an automated caller.
routeExhaustedbooleanSet true alongside status:pending by route_task_model's exhaustion-defer branch (every pool out of headroom for this claimed task). Tracked as a CONSECUTIVE-defer counter (monitoring/task-defer-alerter.ts) that fires its own starvation alert past a threshold; set false (or omit) on a normal working re-stamp to reset the streak.
noopDispatchbooleanRUNNER: repeat-dispatch WARN — set true alongside a review-flip when the commits this fire pushed touched only docs/state paths (no real code change). Tracked as a CONSECUTIVE no-op-dispatch counter (monitoring/task-noop-dispatch-alerter.ts) that WARNs in the runner log past a threshold; set false (or omit) when this fire's commits touched real code, resetting the streak.
pacingDeferbooleanRUNNER: set true alongside status:pending when a POST-CLAIM pacing/routing gate releases a claimed task back to the queue BEFORE it ever routed (reserve-floor restriction on a non-trivial pick, predictive budget gate). Bumps pacingDeferCount so the claim→release churn is queryable (task-d85ea318, the 24:1 claims-vs-executions ratio). Pair with deferSeconds to back off the re-claim. Reset by a normal working re-stamp.
deferSecondsnumberRUNNER: when releasing a claimed task back to status:pending for a pacing/routing reason, push nextRetryAt out this many seconds so the SAME head-of-queue task is not re-claimed on the very next fire (the loop behind the churn). Only honoured with status:pending; clamped to [0, 6h].
dependsOnstring[]REPLACE the task's upstream dependency list (DAG scheduling). Validated: upstreams must exist and the edit must not create a cycle (rejected otherwise). Empty array clears all dependencies — the operator escape hatch for a broken graph.
outputTokensnumberThis fire's actual output-token spend (e.g. cli_task_runner.sh's SESS_TOK/AC_TOK session-token delta). Added onto the task's running outputTokens total. When the task carries a swarmId, the same delta is applied to the owning swarm's cumulative spend and checked against guardrails.checkTokenBudget — meeting the budget pauses the whole swarm and mails the operator (SWARM_MESSAGING P5).

tasks_next

Get the highest-priority pending task (P0 first, then oldest). Optionally filter by repo.

ParameterTypeDescription
repostringOptional repo filter

tasks_claim

Atomically claim the highest-priority pending task (P0 first, then oldest), flipping it pending→working in a single findOneAndUpdate. Cross-machine safe: when two runners fire concurrently against the same queue, exactly one wins each task — no double-pick. Sets claimedBy/claimedAt/leaseUntil for stale-runner reclaim. DAG scheduling: a task with dependsOn is skipped until every upstream task is status done — this applies to explicit taskId claims too (dependency order is correctness, not pacing). Host-aware claiming (task-972913b7): pass localModels (this host's installed Ollama models, e.g. from config/runner_lanes.txt) and a task pinned to a local-lane recommendedModel ("name:tag", e.g. "qwen3-coder:30b") this host lacks is skipped too, same correctness-gate treatment as dependsOn — left pending for a host that does have it. Omit localModels entirely on an older/undeclared caller to never filter. Returns the claimed task, or {claimed:false} when nothing is claimable. Use this from the runner instead of tasks_list + tasks_update.

ParameterTypeDescription
claimedBystringIdentifies the claiming runner/slot, e.g. "runner-host/slot-0"
taskIdstringClaim a specific task by ID (optional)
repostringRestrict the claim to one repo (optional)
ignoreReposstring[]Repos to exclude from the claim (no-autonomous-schedule consent list)
leaseSecondsnumberLease TTL in seconds (default 3600); a working task past leaseUntil is reclaimable
localModelsstring[]This runner host's installed local Ollama models (task-972913b7 host-aware claiming); a pending task pinned to a local model id not in this list is skipped

tasks_fail

Record a genuine runner failure (dead-letter queue + bounded retry-with-backoff). Bumps the task's retry ledger: while under maxRetries (default 3) releases it back to pending with an exponential-backoff nextRetryAt (5m, 10m, 20m, … capped at 6h) so claimTask/tasks_claim won't re-pick it before then. Once retries are exhausted, sets status to dead_letter instead of looping or vanishing — surfaced on the dashboard for operator triage. Use this from the runner's genuine-failure branch INSTEAD OF tasks_update {status:"blocked"}.

ParameterTypeDescription
taskIdstringTask ID that failed
errorstringFailure detail (exit code, error summary, or 3-strikes postmortem) — stored as lastError/notes

tasks_delete

Soft-delete a task: the full doc moves into the tenant's trash bin instead of being destroyed, recoverable via tasks_restore for the retention window (TRASH_RETENTION_DAYS, default 30 days) before the data-retention purge hard-deletes it. Audit-logged (task.trash). A working task is refused — release it first (tasks_fail or tasks_update), so a live runner is never stranded mid-run. Returns the trash entry handle (trashId) plus the deleted task snapshot.

ParameterTypeDescription
taskIdstringTask ID to delete
reasonstringWhy it is being deleted (kept on the trash entry + audit trail)

tasks_restore

Restore a soft-deleted task from the trash bin: re-inserts the original doc (same taskId, fields, timestamps) and consumes the trash entry. Address by trashId (from tasks_delete/trash_list) or by the original taskId. Fails explicitly if an active task under the same taskId was recreated since the delete. Audit-logged (task.restore).

ParameterTypeDescription
trashIdstringTrash entry handle (trash-…) to restore
taskIdstringOriginal taskId, as an alternative lookup to trashId

tasks_bulk

Apply up to 100 task mutations (create / update / cancel / reprioritize) in ONE call — the backend for the multi-repo orchestration board's multi-select actions, so the UI/CLI never needs N round-trips. Ops apply sequentially in array order; each op succeeds or fails INDEPENDENTLY (partial application) and the response reports a per-op verdict {index, action, ok, taskId, task|error+code} plus batch counters {total, succeeded, failed}. Pass stopOnError:true to halt at the first failure (remaining ops report code SKIPPED). Every op goes through the same tenant-scoped single-task write paths as tasks_create/tasks_update, so the bulk-block guard, dependency validation, and status stamps all still apply. Batch refs: anywhere a taskId is accepted (taskId, supersededBy, dependsOn entries), "$N" resolves to the taskId created by op index N earlier in the same batch — lets one call create a dependent chain (op 0 creates migrate-DB, op 1 creates build-UI with dependsOn:["$0"]). cancel = status blocked + a "Cancelled via bulk operation" note (pass reason to elaborate; supersededBy/operatorAuthorized authorize a mass pending→blocked past the guard threshold). reprioritize touches ONLY priority.

ParameterTypeDescription
operationsobject[]The mutations to apply, in order (max 100)
stopOnErrorbooleanHalt at the first failed op; remaining ops report code SKIPPED (default false — partial application)

MAILBOX (durable swarm messaging — SWARM_MESSAGING P1)

mail_send

Send a DURABLE, ADDRESSED message into the fleet mailbox — the path that never loses anything when the recipient is asleep (unlike live SendMessage/SSE, which only work while both ends are online). Addresses are resolved by convention, not a registry: host (e.g. "ph11911"), host/repo (e.g. "ph11911/ai_management"), repo (e.g. "ai_management"), or role (e.g. "reviewer"); to/from are lowercase-normalised so a hostname's casing never strands mail. The message waits unacked until a recipient reads it (mail_inbox) and acks it (mail_ack). ADDITIVE to the notifications event-bus: also emits a message.received event so an open dashboard sees the live toast + history row. Use to hand work across Macs/sessions ("home-mac: continue X") or to exchange notes inside a swarm (swarmId).

ParameterTypeDescription
tostringRecipient address: host \host/repo \repo \role (lowercase-normalised)
fromstringSender address, same forms as to
kindstringFree label: note \request \live-note \swarm (default "note")
subjectstringShort subject line
bodystringMessage body (optional)
replyTostringmessageId this replies to (threading)
swarmIdstringGroups mail exchanged inside one swarm (P2 consumes this)

mail_inbox

Read the mailbox for one or more addresses — UNREAD (unacked) messages only by default, newest first. Pass to as a single address or the full set of addresses this session answers to (its host, host/repo, repo, and role) to drain everything addressed to it in one call. Returns {messages, unreadCount}; unreadCount is the total unacked for the address set regardless of limit (the number the session-start banner shows). Set includeAcked:true to also see already-handled mail. This is a READ — it does not ack; call mail_ack when the message is handled.

ParameterTypeDescription
toanyOne address, or the set of addresses the caller answers to (host, host/repo, repo, role)
includeAckedbooleanInclude already-acked mail too (default false → unread only)
limitnumberMax messages to return (default 50, max 200)

mail_ack

Acknowledge (mark read/handled) one mailbox message by id, so it stops showing as unread in mail_inbox and the session-start banner. Idempotent — acking an already-acked message is a no-op that returns its current state. Returns the updated message, or an error if no message with that id exists for this tenant.

ParameterTypeDescription
idstringThe messageId (mail-…) to acknowledge
ackedBystringWho acked it, for the audit trail (optional, e.g. "ph11911/ai_management")

SWARMS (grouped tasks behind one approval — SWARM_MESSAGING P2)

swarm_plan

Plan a SWARM: one goal split into up to 5 child tasks (cap: SWARM_CHILD_CAP) for one repo, created PAUSED so nothing runs until the operator calls swarm_approve. Children are ordinary tasks stamped with the returned swarmId; a child may wait on EARLIER children via dependsOnIndexes (0-based), which become real dependsOn edges — the runner already defers a child until its upstreams are done. REFUSED for repos on config/schedule_ignore.txt unless consent:true is passed for this call. Returns {swarm, children}.

ParameterTypeDescription
repostringRepo every child runs in (task-store repo name, e.g. "ai_management")
goalstringThe one goal the swarm delivers
createdBystringWho planned it (address: host \host/repo \role) — mailed if the swarm is stopped
childrenobject[]Child tasks in plan order (1..cap)
childCapnumberLower the cap for this swarm (never above the configured cap)
parentTaskIdstringOptional coordinator task every child hangs off
consentbooleanExplicit operator consent for a repo on schedule_ignore.txt (this call only)
notesstring

swarm_approve

Approve a paused swarm (or resume a stopped one): every PAUSED child flips to pending and becomes claimable by any runner; children whose upstreams are not done yet stay deferred by the claim gate. The swarm goes active and is marked done on read once every child is done/review. Returns {swarm, children, approved}.

ParameterTypeDescription
swarmIdstringThe swarm-… id from swarm_plan
approvedBystringWho approved (audit trail)

swarm_stop

KILL SWITCH for a swarm: every open child (pending or working) flips to paused and the swarm goes stopped. A working child's live session is not killed — it finishes its current fire and then cannot be re-claimed. Done/review/blocked children are untouched. Mails every participant (each child's agent) and the swarm's creator via the durable mailbox. Re-approve with swarm_approve to resume. Returns {swarm, children, paused, mailed}.

ParameterTypeDescription
swarmIdstringThe swarm-… id to stop
stoppedBystringWho stopped it (default "operator")
reasonstringIncluded in the mail to participants

swarm_list

List this tenant's swarms, newest first — swarm rows only (goal, repo, status planning|paused|active|stopped|done, childCount, childCap, token budget/spend, who planned/approved/stopped it). Filter by status and/or repo. Call swarm_get for one swarm's children. This is the read the /swarm dashboard renders.

ParameterTypeDescription
statusplanning \paused \active \stopped \doneOnly swarms in this state (optional)
repostringOnly swarms for this repo (optional)
limitnumberMax swarms (default 50, max 200)

swarm_get

One swarm with its children in plan order: each child's taskId, title, raw task status plus a displayStatus (paused|pending|running|done|blocked — the /swarm vocabulary), agent, priority, dependsOn edges (upstream taskIds), claimedBy and prUrl. An active swarm whose children are all done/review is marked done on this read. Returns {swarm, children}.

ParameterTypeDescription
swarmIdstringThe swarm-… id

swarm_update_budget

Set a swarm's output-token BUDGET — the P5 slow-burn guardrail ceiling that pauses the whole swarm once cumulative child spend meets it. Use it to RAISE the budget on a swarm the token-budget guard already paused (bump the ceiling, then swarm_approve to resume), or to tighten one mid-flight. tokenBudget must be a positive number (floored to an integer). Tenant-scoped: an unknown swarm returns an error. Returns {swarm, children}.

ParameterTypeDescription
swarmIdstringThe swarm-… id
tokenBudgetnumberNew output-token budget (positive integer)
bystringWho changed it (audit trail; default "operator")

AGENT DISPATCH (director hands off work — AGENT_MESSAGING_DISPATCH)

dispatch_delegate

The DISPATCH verb: one call for a director session (museum/agy) to hand off work and get a handle back immediately — it never does the work itself. Routes by size/shape: >1 children (or mode:"swarm") plans a SWARM (swarm_plan, still paused pending operator approval — unchanged guardrail); mode:"mail" (or auto with to and no repo) sends a durable kind:request ask to a peer session/role; otherwise creates ONE claimable task addressed to to/assignedAgent. Returns {mode, swarmId|taskId|messageId, ...}. Use this instead of hand-rolling swarm_plan/createTask/mail_send from the director.

ParameterTypeDescription
fromstringThe director's own address (host \host/repo \role) — where result/failure mail comes back to
workstringWhat the work is — becomes the task title / swarm goal / mail subject
descriptionstringLonger detail (task description / mail body)
repostringRepo for a task or swarm delegation
modeauto \swarm \task \mailExplicit routing; default "auto"
tostringRecipient address for a task or mail delegation (host \host/repo \repo \role)
assignedAgentstring
recommendedModelstring
priorityP0 \P1 \P2 \P3
childrenobject[]For mode:"swarm" (or auto with >1 entry): child tasks in plan order
childCapnumber
consentbooleanExplicit operator consent for a schedule_ignore.txt repo (swarm path only)

mail_claim_as_task

WORKER poll: drain one worker address's inbox and turn actionable mail (kind:"request") into tasks already claimed by that worker — the mail-to-task half of agent-to-agent dispatch ("claude-tech asks local Ollama to summarise logs"). REFUSED for a director address (museum/agy/claude-museum never auto-claims — director-only guardrail). Skips self-addressed mail (from === to) and caps conversions per call (default 5, max 20) as flood/loop protection. The mailbox claim is atomic, so two pollers answering the same address can never double-convert one message. Returns the list of {messageId, taskId, from, replyTo, subject} actually converted (empty if nothing actionable or everything lost the race).

ParameterTypeDescription
addressstringThe worker address to drain (host \host/repo \repo \role)
defaultRepostringRepo to file the converted task under
claimedBystringHolder identity claiming the task, e.g. "ph13292/codex"
maxPerPollnumberMax mail converted this call (default 5, max 20)

mail_task_result

WORKER result: reply to a mail-derived task's original requester with kind:"result" (outcome + links) once the task is done or failed — the other half of agent-to-agent dispatch, and how the director hears back (sendMail's existing additive message.received event already reaches the push pipeline, so no separate notification call is needed). Looks up the mail:<id> replyTo:<addr> linkage mail_claim_as_task stamped into the task's notes; a no-op (returns {sent:false}) for an ordinary task that was never mail-derived, so callers can call this unconditionally at task close without checking first.

ParameterTypeDescription
taskIdstringThe mail-derived task that just finished
taskNotesstringThat task's current notes field (read it via tasks_get/listTasks first — carries the mail linkage)
outcomedone \failed
summarystringWhat happened, for the requester
linksstring[]PR / commit / log links
fromstringThis worker's own address (the result mail's from)

DISTRIBUTED TRACING (gateway→runner→agent spans)

traces_record

Record a completed span in the gateway→runner→agent distributed trace for a task (tracing/tracer.ts). Called by the bash runner (scripts/cli_task_runner.sh) to report its own "runner.dispatch" span (claim→CLI-fire) and the "agent.session" span (the headless claude run), correlated with the gateway's own gateway.task_claim/task_update spans via the shared taskId. Never fails the caller — a tracing bug must not break the runner.

ParameterTypeDescription
taskIdstringTask ID this span belongs to — the trace correlation key
namestringSpan name, e.g. "runner.dispatch" or "agent.session"
servicegateway \runner \agentWhich leg of the chain this span represents
startMsnumberSpan start, epoch milliseconds
endMsnumberSpan end, epoch milliseconds
statusok \errorSpan outcome (default ok)
parentNamestringName of the parent span in the same trace, e.g. "gateway.task_claim"
attributesobjectFree-form attributes (repo, model, exitCode, ...)
errorstringError detail when status is error

traces_list

List recent distributed traces (gateway→runner→agent) or the spans of one trace. Backs the minimal /traces viewer. Pass taskId to fetch one trace's spans; omit it to list distinct recent trace IDs.

ParameterTypeDescription
taskIdstringFetch spans for this task's trace only (optional)
limitnumberMax spans/traces to return (default 100)

STRUCTURED REQUEST LOGGING (correlation ids, gateway→runner→agent)

logs_record

Record one structured log line into the tenant-scoped log-store ring buffer (monitoring/log-store.ts) that backs the dashboard's /logs live-tail viewer. Called by the bash runner (scripts/cli_task_runner.sh) so its own log lines for a task thread onto the SAME correlationId the gateway used for that task's HTTP requests (by convention, the taskId). Message and attributes are redacted server-side before storage — never fails the caller.

ParameterTypeDescription
correlationIdstringCorrelation id to thread this line onto — by convention the taskId for task-related lines
servicegateway \runner \agentWhich leg of the chain this line came from
leveldebug \info \warn \errorLog level (default info)
messagestringHuman-readable log message
attributesobjectFree-form structured fields (repo, taskId, exitCode, ...)

logs_list

Query the tenant-scoped structured log-store ring buffer. Filter by correlationId (reconstructs one task's full gateway→runner→agent story), service, level, a text search, or a since epoch-ms cursor for live-tail polling.

ParameterTypeDescription
correlationIdstringOnly entries with this correlation id
servicegateway \runner \agent
leveldebug \info \warn \error
qstringCase-insensitive substring match against the message
sincenumberOnly entries at/after this epoch-ms timestamp (live-tail cursor)
limitnumberMax entries to return (default 200, max 2000)

TASK ARTIFACTS (per-task reviewable output)

artifacts_register

Attach a downloadable artifact (git diff, build/test console output, generated report) to a completed task. Content is capped and compressed server-side. Returns the stored artifact metadata.

ParameterTypeDescription
taskIdstringTask ID this artifact belongs to
repostringRepo the task ran in
kinddiff \build-log \test-report \otherArtifact category
filenamestringSuggested filename for download, e.g. "task.diff", "build.log"
contentTypestringMIME type (default text/plain)
contentstringRaw artifact content

artifacts_list

List artifacts captured for a task (metadata only — no content), newest last.

ParameterTypeDescription
taskIdstringTask ID to list artifacts for

RUNNER JOB HISTORY (searchable overnight-run archive, task-1873b3be)

job_history_record

Record one runner fire into the tenant-scoped, searchable job-history archive (tasks/job-history-store.ts) — repo, task id, outcome (done|blocked|failed|no-result), the RESULT line and a bounded error excerpt. Called by the bash runner at close-off and by scripts/ingest_runner_history.sh backfilling ~/.ai-cli-runner/logs; passing logFile (the host log filename) makes ingestion idempotent (upsert, never a duplicate row). Text is redacted + capped server-side; retention (age + per-tenant cap) is applied on write.

ParameterTypeDescription
repostringRepo the job ran in
taskIdstringFleet-queue task id the job worked
statusdone \blocked \failed \no-resultRun outcome — done (RESULT line, pushed), blocked (RESULT: BLOCKED), failed (non-zero exit), no-result (no RESULT line in the log)
resultLinestringThe run's final "RESULT: " line (capped server-side)
errorExcerptstringBounded error/postmortem excerpt — e.g. the 3-strikes stop block or the tail of a failed run (capped server-side)
exitCodenumberCLI exit code (optional)
machinestringRunner hostname (optional)
modelstringModel the session ran on (optional)
logFilestringSource log filename on the runner host — idempotent-ingest dedupe key (optional but strongly recommended)
startedAtMsnumberEpoch ms the job fired (from the log filename timestamp; default now)
durationSecondsnumberWall-clock seconds the job ran (optional)

Search the tenant-scoped runner job-history archive — past overnight/scheduled runs indexed by repo, task id, outcome status, and error/RESULT substring — instead of grepping raw log files on whichever Mac ran them. Backs the dashboard /runs page. Newest first; returns the pre-limit total for pagination.

ParameterTypeDescription
repostringOnly runs in this repo (exact match)
taskIdstringOnly runs for this task id (exact match)
statusdone \blocked \failed \no-resultOnly runs with this outcome
qstringCase-insensitive substring over the RESULT line + error excerpt
sincenumberOnly runs started at/after this epoch-ms timestamp
untilnumberOnly runs started at/before this epoch-ms timestamp
limitnumberMax entries to return (default 50, max 500)

RUNNER LEASES (ADR-011 slice 3 — fleet-wide concurrency)

runner_lease_acquire

Acquire one of the N fleet-wide runner-lease slots (N = active Claude accounts, default 2) before starting an autonomous session. Cross-machine safe: slots live in the shared runner_leases collection, so at most N sessions run fleet-wide no matter how many Macs fire. Atomically reclaims a stale slot (crashed runner past leaseUntil) and is idempotent for the same holder. Returns {acquired:true, lease} or {acquired:false} when all slots are validly held — back off, do not start a session.

ParameterTypeDescription
holderstringRunner identity, e.g. "runner-host/12345" (hostname/pid)
machinestringHostname, for fleet visibility (optional)
accountstringClaude account/profile bound to this run, e.g. "claude-tech" (optional)
taskIdstringTask being worked under this lease (optional, visibility)
slotsnumberSlot-pool size override (default 2 = active accounts)
leaseSecondsnumberLease TTL in seconds (default 3600 — covers the 45-min session cap with margin)

runner_lease_heartbeat

Extend a held runner-lease slot (resets leaseUntil to now + leaseSeconds). Only succeeds while the slot still belongs to this holder; {ok:false} means the lease was reclaimed after going stale — the runner must stop claiming new work. Optionally stamps the taskId being worked. If account is given and differs from the account the slot was acquired with, the slot is released instead of extended (profile drift — see runner_lease_acquire's account field) and {ok:false} is returned.

ParameterTypeDescription
holderstringRunner identity that acquired the slot
slotnumberSlot index returned by runner_lease_acquire
leaseSecondsnumberNew TTL in seconds from now (default 3600)
taskIdstringTask being worked (optional, visibility)
accountstringClaude account/profile the caller is currently running under (optional). Validated against the account the slot was acquired with (slice 6).

runner_lease_release

Release a held runner-lease slot when the session ends, freeing it for the next fire. Holder-scoped (cannot free a slot another runner reclaimed) and idempotent: releasing an already-released slot returns {released:false}, not an error.

ParameterTypeDescription
holderstringRunner identity that acquired the slot
slotnumberSlot index to release

runner_lease_list

List runner-lease slots for this tenant: holder, machine, account, taskId, heartbeat, leaseUntil and a stale flag per slot, plus active/max counts. Read-only fleet visibility (dashboard, debugging "why is the runner backing off").

ParameterTypeDescription
slotsnumberSlot-pool size for the maxSlots readout (default 2)

runner_lease_history

Runs log (ADR-011 slice 7): newest-first history of completed runner-lease holds — slot, holder, machine, account, taskId, acquiredAt/releasedAt/durationMs, and why it ended (released | reclaimed | account_mismatch). Written when a slot stops being held, since the live RunnerLease doc (runner_lease_list) is deleted on release. Powers the dashboard runner-leases view — replaces grepping raw Mongo to debug a starved queue or a suspiciously slow account.

ParameterTypeDescription
limitnumberMax rows to return, newest first (default 50, max 500)
accountstringFilter to one Claude account/profile, e.g. "claude-tech"
slotnumberFilter to one slot index

lease_acquire

Acquire a KEYED lease — a named, tenant-scoped lock for coordinator election (key "swarm-coordinator:<host>") or a resource claim (key "claim:<repo>:<path>"). Distinct from runner_lease_* (the runner's fixed N-slot concurrency pool): keyed leases never consume runner slots. Inserts when the key is free, atomically takes over a stale lease, and is idempotent for the same holder string (extends it). Expiry is judged by Mongo SERVER time, so gateways with skewed clocks agree. holder must be "<host>/<lane>/<pid>" — the pid makes idempotency per process, so a restarted session cannot inherit its dead predecessor's lease. Returns {acquired:true, lease:{…, epoch}, tookOverFrom?} or {acquired:false, heldBy}. HOLD the returned lease.epoch (fencing token: 1 on insert, +1 on every takeover) and pass it to lease_heartbeat / lease_release. Do not act as holder unless acquired is true.

ParameterTypeDescription
keystringLease name, 1-200 chars, no whitespace, e.g. "swarm-coordinator:ph13292" or "claim:ai_management:scripts/lib/session_lanes.sh"
holderstringProcess identity "<host>/<lane>/<pid>", e.g. "ph13292/museum/4242" (>=2 non-empty "/"-separated segments, 3-200 chars, no whitespace)
leaseSecondsnumberLease TTL in seconds (default 600, clamped 30-86400). Heartbeat before it lapses.
metaobjectSmall visibility metadata, e.g. {lane, pid, host, note} (max 2048 bytes as JSON; keys must not start with "$" or contain ".")

lease_heartbeat

Extend a held KEYED lease (leaseUntil = Mongo server now + leaseSeconds). Pass the epoch lease_acquire returned: the heartbeat only succeeds while the key still belongs to this holder AND (when given) the epoch matches. {ok:false, heldBy?} means the lease was taken over after going stale, or released — the caller has LOST it and must stop acting as holder (e.g. stop coordinating). Never changes the epoch. Distinct from runner_lease_heartbeat (slot pool).

ParameterTypeDescription
keystringLease name passed to lease_acquire
holderstringHolder string that acquired the lease ("<host>/<lane>/<pid>")
epochnumberFencing token from lease_acquire (recommended). Mismatch → {ok:false}.
leaseSecondsnumberNew TTL in seconds from server now (default 600, clamped 30-86400)

lease_release

Release a KEYED lease (coordinator step-down, claim done). Pass the epoch lease_acquire returned; on mismatch nothing is deleted ({released:false}). Holder-scoped: cannot free a lease another holder took over. force:true deletes regardless of holder — operator override for a wedged holder; REQUIRES the configure capability (plain release needs only work). Idempotent: an absent lease returns {released:false}. Distinct from runner_lease_release (slot pool).

ParameterTypeDescription
keystringLease name to release
holderstringHolder string that acquired the lease (recorded in logs even with force)
epochnumberFencing token from lease_acquire (recommended). Mismatch → {released:false}, also under force.
forcebooleanOperator override: delete regardless of holder (default false; needs the configure capability)

lease_list

List KEYED leases for this tenant, sorted by key: key, holder, epoch, acquiredAt, heartbeatAt, leaseUntil, meta and a stale flag computed against Mongo server time. Filter with prefix, e.g. "swarm-coordinator:" (who is coordinator) or "claim:ai_management:" (who holds which files). limit default 200, max 1000; truncated:true means more matched. Read-only. Distinct from runner_lease_list (slot pool).

ParameterTypeDescription
prefixstringLiteral key prefix filter (not a regex), e.g. "claim:ai_management:"
limitnumberMax leases to return (default 200, max 1000)

runner_heartbeat

Record one liveness pulse for a runner machine. Call once per fire, before task pickup, regardless of whether a task gets claimed — this tracks "the runner process is alive", not "there was work to do". Distinct from runner_lease_heartbeat, which only extends a held concurrency slot mid-session. AGENT_MESSAGING_DISPATCH: optionally also registers this runner's mailbox address + capabilities (lane, installed models) — the identity record a non-Claude CLI lane (agy, codex, local Ollama) has no other way to publish. Omit either to leave the previously registered value alone.

ParameterTypeDescription
machinestringHostname the runner fired on, e.g. "runner-host"
holderstringRunner identity for this fire, e.g. "runner-host/12345" (hostname/pid)
addressstringMailbox address this runner answers to (host \host/repo \role), e.g. "ph13292/codex"
capabilitiesstring[]Capability tags: lane name, installed models, skills (e.g. ["codex","review"] or ["ollama","qwen3-coder:30b"])

runner_liveness

Read fleet-wide runner liveness: per-machine last-heartbeat age and a "down" flag once it exceeds thresholdMinutes (default 25 — 2.5x the 10-min fire cadence), plus overall alive (true iff any machine heartbeated within threshold). Used by the dashboard "runner down / last seen X ago" banner and the health-alerter.

ParameterTypeDescription
thresholdMinutesnumberLiveness threshold in minutes (default 25)

worker_lane_status

Tenant-scoped read: connected | down | not-configured per execution lane (Claude claude-tech, Claude Fable, the director-only museum profile, Codex, Antigravity, Copilot, local Ollama, DeepSeek/Kimi API), joined with host + last-check from runner_heartbeat capability tags and executions in the last 24h/30d from Task.executionProvider/executionLane/routedModel. Powers the /swarm "Workers" panel.

ParameterTypeDescription
thresholdMinutesnumberLiveness threshold in minutes (default 25) — a lane's heartbeat older than this reads "down" instead of "connected".

RUNNER BACKLOG CURSOR (task-e9163eb9 — cross-machine backlog well)

backlog_cursor_get

Read the cross-machine runner-backlog well cursor: how many config/runner_backlog.jsonl lines have been consumed (popped) so far. Replaces the gitignored, machine-local config/.runner_backlog.cursor file so scripts/queue_topup.sh --report and its low-backlog check agree regardless of which machine or worktree runs them. One counter per tenant; returns 0 when never set.

No parameters.

backlog_cursor_set

Set the cross-machine runner-backlog well cursor (consumed count) — task-e9163eb9. Called by scripts/queue_topup.sh after popping backlog items or after its self-heal recomputes a corrected consumed count.

ParameterTypeDescription
consumednumberNew consumed count (non-negative integer)

RUNNER BACKLOG CONSUMED-TITLES LEDGER (task-aa331af6)

backlog_ledger_get

Read the durable runner-backlog consumed-titles ledger (task-aa331af6): every backlog line title ever positively confirmed to have a matching gateway task. Unlike a tasks_list(limit:2000) lookup, membership here never ages out as the fleet-wide task table grows — used by scripts/queue_topup.sh self-heal as a floor the corrected cursor may never rewind past.

No parameters.

backlog_ledger_add

Add title(s) to the durable consumed-titles ledger (task-aa331af6), idempotent set semantics. Called by scripts/queue_topup.sh whenever it positively confirms a backlog line already has a matching gateway task (exact-title dedupe match or self-heal confirmation), so the confirmation survives even after the title ages out of tasks_list's limit:2000 window.

ParameterTypeDescription
titlesstring[]Backlog line titles to mark as confirmed-consumed

REPOS

repos_list

List all managed repos from managed_repos.txt with health indicators (exists, is git repo, has AI/, has state + handoff).

No parameters.

repos_status

Detailed status for a repo: current branch, uncommitted file count, ahead/behind counts, last handoff/state modification time.

ParameterTypeDescription
repostringRepo name or absolute path

repos_priority

Rank managed repos by attention needed: open task count, stale handoff, missing AI framework. Highest score first.

No parameters.

repos_scan

Scan a directory to discover git repositories and their tech stacks. Returns discovered repos with name, path, stack detection (Next.js, Express, Docker, MongoDB, TypeScript, Python), and whether the AI framework is already installed. Use to discover repos before registering them.

ParameterTypeDescription
pathstringAbsolute directory path to scan
maxDepthnumberMax directory depth to search (default 4)
registerbooleanIf true, upsert discovered repos into the caller's tenant repos DB roster (ADR-021) and append them to managed_repos.txt (default false)

repos_upsert

ADR-021 Phase 2 — self-register (or refresh) one repo in the caller's tenant repos DB roster. Used by myai init (source: myai-init), myai scan --register (source: scan), and myai new-app <idea>'s headless agentFlow pipeline (source: headless-new-app) so a repo's fleet-tracking entry lives under the owning tenant instead of the shared managed_repos.txt.

ParameterTypeDescription
namestringRepo name (unique per tenant)
pathstringAbsolute local checkout path
gitRemotestringOrigin remote URL, if any
brainNamespacestringBrain namespace this repo resolves to
stackstring[]Detected tech stack tags
groupstringOptional dashboard grouping label
sourceseed \myai-init \scan \manual \headless-new-appProvenance of this entry (default manual)
enabledbooleanWhether this repo is active in the roster (default true)

get_pr_impact

Blast radius for a change: given a set of changed files (or a base...head git diff), returns every in-repo file transitively affected via the deterministic typed code-edge graph (git-tracked TS/JS/Python, regex-resolved import/calls/tests_of edges — same class of heuristic as scripts/scan_repo_index.py + scripts/code_graph.py, not a real compiler). affectedFiles is the import-based blast radius; callers surfaces files that call into a changed file even without importing it; affectedTests lists tests covering the impacted footprint. Use before re-reading files to reason about a PR/diff's reach: unaffected files can be skipped. Aliased/bare-package imports and uncommon call patterns are not resolved, so this is a lower bound on impact.

ParameterTypeDescription
repostringRepo name (from managed_repos.txt) or absolute path. Defaults to the framework root.
filesstring[]Explicit list of changed file paths (repo-relative). Takes precedence over base/head.
basestringBase git ref for a diff (used with head if files is omitted)
headstringHead git ref for a diff (used with base if files is omitted)
maxDepthnumberMax BFS hops to traverse for the blast radius (default 6)

triage_prs

Rank a set of open PRs by risk/impact using get_pr_impact's blast radius plus heuristics (infra/config/schema files touched, source changes with no accompanying test file, no known test coverage anywhere in the impacted footprint per the tests_of edge, blast radius exceeding the depth cap). Highest risk first. Feed the PR-review swarm and the runner's pre-claim preflight this instead of re-reading every changed file per PR.

ParameterTypeDescription
repostringRepo name (from managed_repos.txt) or absolute path. Defaults to the framework root.
prsobject[]Array of {id, label?, files?, base?, head?} — one entry per PR. Each needs either files or both base and head.
maxDepthnumberMax BFS hops per PR's blast radius (default 6)

get_neighbors

Typed neighbors of one node in the deterministic code-edge graph (B-1.5) — a scoped subgraph, not raw files. node is a repo-relative file path OR a declared symbol (function/class/const) name, resolved to its declaring file(s). Returns each neighbor's edge type (import/calls/tests_of), direction, and file — never file contents. Same-process TS counterpart to scripts/code_graph.py get_neighbors(); use to answer "what does X import/call" or "what calls/imports/tests X" without re-reading files.

ParameterTypeDescription
repostringRepo name (from managed_repos.txt) or absolute path. Defaults to the framework root.
nodestringRepo-relative file path or a declared symbol name
directionout \in \bothout = this node's outgoing edges, in = incoming, both (default out)
edgeTypesstring[]Subset of edge types to traverse (default all three)

shortest_path

Shortest typed-edge path between two nodes in the deterministic code-edge graph (B-1.5) — returns the file path chain, not file contents. src/dst are repo-relative file paths OR declared symbol names (resolved to declaring file(s); ambiguous symbols try every candidate file pair and keep the shortest). BFS over import/calls/tests_of edges, same heuristic class as scripts/code_graph.py shortest_path(). Null path means unreachable within the selected edge types.

ParameterTypeDescription
repostringRepo name (from managed_repos.txt) or absolute path. Defaults to the framework root.
srcstringStarting repo-relative file path or symbol name
dststringTarget repo-relative file path or symbol name
edgeTypesstring[]Subset of edge types to traverse (default all three)

plan_list

List the 10-day improvement plan (day-by-day focus schedule) for a repo (or all repos). Each day has a fire time (UTC, ≈9am Sydney), a one-line focus, and a status. Rendered as a table on the dashboard /plan page. Bounded to limit rows (default 200); when more rows exist past this page, the response carries a nextCursor — pass it back as cursor to fetch the next page. Omitting cursor always starts from the beginning, so existing callers are unaffected.

ParameterTypeDescription
repostringRepo name (optional — omit for all repos)
limitnumberMax results per page (default 200)
cursorstringOpaque pagination cursor from a prior response's nextCursor (optional — omit for the first page)

plan_set

Set/replace a repo's multi-day improvement plan. Pass an array of {day, focus, status?} and a startDate; fire times auto-compute (day 1 = startDate at the off-hours default 10:00 UTC ≈ 8pm Sydney, then +1 day each). OFF-HOURS POLICY: any fire time landing in the user's weekday interactive window (9am–6pm Sydney) is auto-clamped into the 6pm–9am off-hours band. Use after producing the mythos improvement plan, alongside scheduling the actual tasks via schedule_task.sh.

ParameterTypeDescription
repostringRepo name
startDatestringISO date for day 1 (default: today)
fireHourUtcnumberUTC hour each day fires (default 23 ≈ 9am Sydney AEST)
replacebooleanClear existing days first (default false). SOFT delete: the replaced days move into the trash bin (recoverable via plan_restore for the retention window), never a hard wipe.
daysobject[]Array of {day:number, focus:string, status?:enabled\disabled\done\blocked}

plan_delete

Soft-delete a repo's entire multi-day plan: every PlanDay snapshots into ONE trash-bin entry instead of being destroyed, recoverable via plan_restore for the retention window (TRASH_RETENTION_DAYS, default 30 days). Audit-logged (plan.trash). Returns the trash entry handle (trashId) + day count.

ParameterTypeDescription
repostringRepo whose plan to delete
reasonstringWhy it is being deleted (kept on the trash entry + audit trail)

plan_restore

Restore a soft-deleted plan from the trash bin. Address by trashId, or by repo to restore that repo's NEWEST trashed plan (covers the accidental plan_set replace:true — the replaced days are in trash). Days whose {repo, day} slot is now occupied by a live plan row are SKIPPED and stay in the trash entry (restore never clobbers current work); the response reports restoredDays vs skippedConflicts explicitly. Audit-logged (plan.restore).

ParameterTypeDescription
trashIdstringTrash entry handle (trash-…) to restore
repostringRepo name, as an alternative lookup — restores its newest trashed plan

trash_list

List the tenant's trash bin — soft-deleted tasks and plans still inside the retention window (TRASH_RETENTION_DAYS, default 30 days), newest first. Each entry carries trashId (the tasks_restore/plan_restore handle), kind, label, repo, item count, who deleted it, why, when, and purgeAfter (when the data-retention purge may hard-delete it).

ParameterTypeDescription
kindtask \planFilter to one kind (optional)
repostringFilter by repo (optional)
limitnumberMax entries (default 50)

HANDOFF (betaC — first-class handoff store)

handoff_write

Write a session handoff for a repo to the gateway (betaC first-class handoff store). Append-only — each call adds a new entry, building an auditable handoff trail across sessions and machines. Replaces git-syncing AI_AGENT_HANDOFF.md: the next agent reads the latest handoff from the gateway instead of pulling main. Pass the full handoff body in content and a one-line "what's next" in summary.

ParameterTypeDescription
repostringRepo name the handoff belongs to
contentstringFull handoff body (markdown): done / in-progress / next / blockers
summarystringOne-line "what's next" headline (optional)
authorstringAgent/profile/machine that wrote it (optional)
branchstringGit branch the handoff was written from (optional)
machinestringHostname the session ran on (optional)
sessionIdstringOriginating gateway session id (optional)

handoff_read

Read the latest session handoff for a repo from the gateway (betaC first-class handoff store). Returns the most recent entry (the "what's next" the next agent needs) plus the total entry count. Pass history > 0 to also get that many recent entries (newest first). Omit repo to list the latest handoff for every repo the tenant has.

ParameterTypeDescription
repostringRepo name (omit to list the latest handoff per repo)
historynumberAlso return this many recent entries newest-first (default 0 = latest only)
limitnumberWhen repo is omitted: max repos to list (default 100)

SESSION export / import + cross-session recall (betaC context-SHARING)

session_export

Export a live or persisted session as a portable bundle so its context can follow the user to another device (betaC context-sharing). Returns a versioned, tenant-owned snapshot (agent, status, full message history, workspace, metadata) — prefers the durable DB copy, falls back to the in-memory cache. Pass the bundle to session_import on the other device.

ParameterTypeDescription
sessionIdstringId of the session to export

session_import

Import a session bundle produced by session_export so context follows the user across devices (betaC context-sharing). The session is stamped with the importing tenant (a bundle can never smuggle a foreign tenant), loaded into the live cache and persisted. By default a fresh session id is minted so cross-device imports never collide; set preserveId to keep the original id (idempotent same-device re-import).

ParameterTypeDescription
bundleobjectThe export bundle returned by session_export ({ version, exportedAt, session })
preserveIdbooleanKeep the bundle's original session id and update in place instead of minting a new one (default false)

session_recall

Recall the tenant's recent sessions into a single ready-to-inject context block so a fresh session — typically on another device — resumes with continuity (betaC context-sharing). Returns the recent sessions (agent, status, recent messages) plus a markdown digest. Filter to one agent with agentName.

ParameterTypeDescription
agentNamestringOnly recall sessions for this agent (optional)
limitnumberMax sessions to recall (default 5)
perSessionMessagesnumberRecent messages to include per session (default 4)

context_boot

Fetch the betaC boot bundle ON DEMAND — the tight, token-budgeted OPERATOR BRIEF a blank agent needs to greet the operator and continue the work. Returns bundle (rendered markdown) plus brief structured as who / state / handoff / next: WHO you are working with, the STATE (active project), the last HANDOFF summary, and what comes NEXT from the active plan — plus manifest, the compact BRAIN B-2 control-plane TOC (stores + fetch tools, namespace count, active-namespace freshness, freshness SHA) so you know WHERE everything lives without scanning state files. The rendered bundle is B-8 prompt-cache ordered: byte-stable content (identity, recall pointers, store TOC) above the <!-- B-8 cache boundary --> marker, volatile content (brain SHA, handoff, next) below — so wakeup-to-wakeup prompt-cache prefix hits survive brain churn. This is the callable form of the auto-boot the gateway injects on MCP initialize: use it from the wrap-it tier (a blank ChatGPT/Ollama via a thin shim that cannot read InitializeResult.instructions) or to RE-fetch a fresh bundle mid-session. CHEAP BY DESIGN: with no query it returns only the tight brief and runs NO search. Pass a query to LAZILY pull deeper context — one capped semantic search whose short snippet pointers are returned under deeper — so depth is opt-in and auto-boot fixes token-burn instead of recreating it. For full depth, follow the returned lazyRecall tools (handoff_read / recall_session / memory_search).

ParameterTypeDescription
repostringOverride the active project (default: highest-priority repo, else master)
querystringFocus query — when present, lazily pulls deeper RAG context into deeper (omit to keep the bundle a tight, zero-search summary)
expandLimitnumberMax deeper snippets when query is set (default 4, hard cap 8)
crossProjectbooleanSearch the whole tenant memory (global layer) instead of just the active project (default false)
budgetnumberChar budget for the tight summary (default BETAC_BUDGET_CHARS / 1800)

continuity_stats

The cold-start tokens-saved meter. Every context_boot bundle, brain_delta catch-up, and memory_context block the gateway serves is metered (estimated tokens = the re-teaching cost the operator avoided, plus the real wall-clock ms taken to assemble it); this tool returns the tenant-scoped rollup: month-to-date and all-time boots + tokens saved, split by serving tool, plus coldStart — the today-vs-brain comparison (avg tokens per session start on the brain path vs the measured legacy file-read baseline) — and timeToContext — the SAME comparison in wall-clock ms (measured brain-path assembly time vs. the legacy baseline tokens converted to an estimated skim-reading time). Surfaced on the dashboard /analytics page and in myai status — the headline continuity number ("myAI saved N tokens this month").

ParameterTypeDescription
repostringScope the rollup to one repo (optional; default: whole tenant)

user_savings

Per-user cumulative cold-start savings + the shareable "myAI saved me N tokens / $X this month" figure. Returns month-to-date and all-time tokens saved with their USD value (cold-start tokens priced at the input-token tier the model would otherwise re-ingest). Pass userId to scope to one tenant member (the share-card number); omit it for the whole-tenant total plus a month-to-date per-member breakdown (byUser, highest first). Powers the dashboard /savings view and the /savings/card share image.

ParameterTypeDescription
userIdstringScope to one tenant member (optional; default: whole-tenant total + per-member breakdown)

activation_funnel

The activation funnel — privacy-respecting product analytics with NO third-party tracker. Returns the tenant's own onboarding journey (steps signup → init → first_brain_boot → first_brain_delta → wrapup_merge, which are reached, when, and activation %). Pass fleet:true for the operator/product rollup instead: distinct tenants at each step, per-step conversion, and the headline activationRate (activated ÷ signed-up). Pass selfServe:true for the plain sellable-product view instead: signup → init → first task shipped → retained (2nd task shipped), with the headline conversionRate (retained ÷ signed-up) — the self-serve conversion number, distinct from the continuity-aha activation rate. Pass hostedBrain:true for the cross-machine-sync conversion KPI (ADR-023 Slice P3): signups vs. distinct tenants who completed their first hosted-brain provision, with the headline conversionRate. Pass dropoff:true for the operator activation-journey drop-off report instead (dashboard /analytics/funnel): the signup → project-connected → first-task-executed → first-task-shipped funnel with an explicit per-stage droppedOff count/%, the worstStage (largest leak), and the SAME funnel broken out per signup cohort (cohort:"month" default or "week", sinceDays bounds the window) — the where-do-signups-fall-out view, distinct from the continuity-aha and self-serve funnels. Milestones are stamped first-touch from existing gateway chokepoints (ADR-014 usage-metering write path) and surfaced on the dashboard /analytics page.

ParameterTypeDescription
fleetbooleanReturn the cross-tenant fleet rollup + activation rate instead of this tenant's own journey (operator view; default false)
sinceDaysnumberFor the fleet rollup and drop-off views — bound to milestones that occurred in the last N days (optional)
selfServebooleanReturn the self-serve conversion funnel instead (signup → init → first task shipped → retained); takes precedence over fleet (default false)
hostedBrainbooleanReturn the cross-machine-sync (hosted brain) conversion funnel instead (signup → first hosted-brain provision); takes precedence over fleet/selfServe (default false)
dropoffbooleanReturn the operator activation-journey drop-off + signup-cohort report instead (signup → init → first_task → first_ship with per-stage droppedOff, worstStage, and per-cohort funnels); takes precedence over the other views (default false)
cohortmonth \weekFor dropoff only — signup-cohort granularity (default month)

perf_stats

Gateway hot-path performance meter. Every MCP tool call is timed at the single executeTool chokepoint; this returns the live in-process rollup: per-tool count / avg / p50 / p95 / p99 / max latency (ms), the aggregate p95, a slow-query log of the most recent calls over the slow threshold (default 500ms, MYAI_SLOW_QUERY_MS), and hotPaths (the tools accumulating the most slow hits). Surfaced on the dashboard /analytics "Gateway performance" card. In-process + bounded — no DB write on the hot path, so it never adds latency; state resets on gateway restart (this is a live operational meter, not a historical store).

No parameters.

slo_status

Per-route SLO alerting status. Returns the active SLO configuration (default p95-latency + error-rate thresholds, per-route overrides, min-sample floor, cooldown), and — evaluating the live perf meter right now — the routes currently breaching their SLO. The gateway fires cooldown-guarded Telegram alerts on breach (via the notification engine); this tool is the read-only view of that alerter. Disable alerting with SLO_ALERTS_DISABLED=1; tune with MYAI_SLO_P95_MS / MYAI_SLO_ERROR_RATE_PCT / MYAI_SLO_ROUTES (JSON per-route overrides) / MYAI_SLO_MIN_SAMPLES / MYAI_SLO_COOLDOWN_MIN.

No parameters.

canary_status

Synthetic-canary probe status. The gateway proactively runs a scheduled end-to-end synthetic transaction through the control plane — signup → task dispatch → runner pickup (tasks_claim) → ship (review→done) — in a fully isolated, auto-purged synthetic tenant, and alerts via the notification engine (+ Telegram/Slack) when a stage fails or degrades past its latency budget. Distinct from slo_status (reactive, needs real traffic). Returns the active configuration (cadence, per-stage budgets, cooldown, degraded-streak threshold), the latest run (per-stage pass/fail + latency vs budget), and the bounded run history. Disable with SYNTHETIC_CANARY_DISABLED=1; tune with MYAI_CANARY_INTERVAL_MIN / MYAI_CANARY_BUDGETS_MS (JSON per-stage ms) / MYAI_CANARY_COOLDOWN_MIN / MYAI_CANARY_DEGRADED_STREAK.

No parameters.

repos_card_list

List the app-directory cards for every tracked repo — the one-point pointer showing each app's localhost address, app/api URLs, MongoDB (non-secret label), Vercel/DNS URLs, short description, and rolling last-update status. Populated by each repo on wrap up.

No parameters.

repos_card_upsert

Create or update THIS repo's app-directory card. Only provided fields are written (partial update), so a wrap-up can refresh just the status without clobbering the URLs. Store NON-SECRET values only for mongo (e.g. host + db name, never a connection string with credentials).

ParameterTypeDescription
repoNamestringRepo name (unique key, e.g. git basename)
descriptionstringShort one-line description of the app
groupstringOptional grouping label
localhostUrlstringLocal dev address, e.g. http://localhost:3000
appUrlstringProduction app URL
apiUrlstringAPI base URL
mongostringNON-SECRET Mongo label, e.g. "Atlas cluster0 / db myapp" or "local :27017/myapp"
vercelUrlstringVercel deployment URL
dnsUrlstringCustom domain / DNS URL
lastStatusstringRolling status free-text (git summary / what last shipped)
lastStatusLevelok \warn \error \unknownStatus dot colour
reportedBystringAgent/profile updating the card
commitsAheadnumbergit rev-list --count origin/main..origin/test — how many unshipped commits are sitting on test

new_app

Spin up a brand-new app from a plain-English idea: drives agentFlow's idea→app pipeline (project create + auto-run codegen→runner bridge) and registers the generated repo in the gateway app-directory so it shows on the dashboard. Backs the myai new-app "<idea>" CLI command. Requires AGENTFLOW_URL + AGENTFLOW_TOKEN env for the trigger; the card is registered regardless so the app is always tracked.

ParameterTypeDescription
ideastringPlain-English description of the app to build
namestringOptional explicit project/repo name (defaults to a slug of the idea)
groupstringOptional directory grouping label (default "Generated")
triggerbooleanStart agentFlow's full auto-run pipeline immediately (default true). When false, only create the project + register the card.

CONNECTORS (bundled MCP connector set + per-tenant manager)

connectors_list

List this tenant's MCP connectors — the curated bundled set (betaC gateway, Context7, shadcn/ui, Playwright, GitHub, Vercel, Dropbox) plus any custom connectors. Auto-seeds the bundle on first read so a fresh install is never empty. Each entry shows transport (http/stdio), enabled state, source (bundled/custom), and any env vars (e.g. a GitHub PAT) the operator still needs to supply.

No parameters.

connectors_seed_defaults

Seed (or refresh) the curated default MCP connector bundle for this tenant so a fresh betaC install has working connectors day one. Idempotent — bundled catalog fields are refreshed but an existing connector's enabled toggle is preserved. Returns counts of newly seeded vs already present.

No parameters.

connectors_set

Create or update a connector. For a CUSTOM connector supply transport + url (http) or command/args (stdio). For a BUNDLED connector you can pass just {key, enabled} to toggle it without resupplying catalog fields.

ParameterTypeDescription
keystringConnector slug (also the key under mcpServers in .mcp.json)
labelstringDisplay label
categorystringframework \docs \design \browser \vcs \deploy \storage \custom
transporthttp \stdiohttp (url) or stdio (command/args)
descriptionstring
urlstringhttp transport — MCP endpoint URL
commandstringstdio transport — launch command, e.g. npx
argsstring[]stdio transport — command args
envobjectEnv passed to the server / http headers (values may be ${VAR})
requiresEnvstring[]Env var names the operator must supply
enabledbooleanWhether the connector is active

connectors_toggle

Enable or disable a connector by key. Convenience over connectors_set for the dashboard toggle.

ParameterTypeDescription
keystring
enabledboolean

connectors_remove

Remove a connector. Custom connectors are deleted; bundled connectors are disabled instead (a re-seed would otherwise bring them back). Returns whether it was removed vs disabled.

ParameterTypeDescription
keystring

connectors_mcp_config

Build an .mcp.json-shaped object from this tenant's ENABLED connectors — the artifact a scaffolded project or CLI session consumes to get working connectors day one.

No parameters.

FLEET RUN (morning "agent mode -resume all" console)

fleet_run_start

Open a fleet morning-sweep run. The master repo aggregates each managed repo's overnight state (commits / open PRs / runner activity / queued review+blocked tasks) into repos[] with a per-repo recommendation. Renders live on the dashboard /fleet page. Keyed by runId (re-running the same runId replaces it).

ParameterTypeDescription
runIdstringUnique run id, e.g. "fleet-20260616-0830"
typestringRun type (default morning-resume-all)
machinestringHostname the sweep ran on
agentstringAgent/profile that opened the run
reposobject[]Per-repo overnight state + recommendation

fleet_run_repo_update

Update ONE repo's live progress within a fleet run as the operator approves and the agent executes an action (merge/fix/test/ship/wrap-up). Flips actionStatus and appends a detail line so the dashboard /fleet page reflects work in realtime.

ParameterTypeDescription
runIdstring
repostring
decisionstringWhat the operator chose
actionstringship \fix \merge \test \wrap-up \skip
actionStatuspending \in-progress \done \failed \skipped
detailstringRolling progress / result line
prUrlstring
recommendationstring

fleet_run_finish

Close a fleet run (status completed or aborted) and stamp the final summary.

ParameterTypeDescription
runIdstring
statuscompleted \aborted

fleet_run_latest

Get the most recent fleet run (what the dashboard /fleet page shows). Returns null if no run yet.

No parameters.

fleet_run_list

List recent fleet runs (history of morning sweeps), most recent first.

ParameterTypeDescription
limitnumberMax runs (default 20)

AGENTS / SKILLS

agents_list

List all loaded specialist agents with name, category, description, and tool count.

ParameterTypeDescription
categorystringFilter by category (core, swarm, dev, analysis, neural, github, ops, data, content)

skills_list

List all loaded skills with name, description, and trigger keywords.

ParameterTypeDescription
agentstringFilter to skills owned by a specific agent (optional)

agents_invoke

Invoke a specialist agent with a task message. Loads the agent's instructions as the system prompt, calls the configured LLM provider, and returns the response. Optionally injects memory_context for the target repo to ground the answer in current state.

ParameterTypeDescription
agentstringAgent name (e.g. solution-architect, security-specialist)
messagestringTask or question to send to the agent
repostringRepo name for memory context lookup (optional)
includeMemoryContextbooleanPrepend memory_context block to the message (default false). Requires repo.
maxTokensnumberMax output tokens (default 4096)
tierbudget \standard \premium \ultra \fable \kimiExplicit routing tier override (optional). Default: determined by agent name.
workTypeagentic-interactive \agentic-autonomous \frontend \backend \docs \chat \research \code-review \architecture \database \security \data-embeddings \summarize-extractDeclared work-type hint (plan/MULTI_PROVIDER_ORCHESTRATION.md §3) — resolves to the doc's intended primary engine + first-hop failover. Below an explicit tier override, above agent-name routing (optional).

skills_invoke

Invoke a skill with a task message. Loads the skill's playbook as the system prompt, calls the configured LLM provider, and returns the response.

ParameterTypeDescription
skillstringSkill name (e.g. owasp-audit, code-review)
messagestringTask or question to apply the skill to
maxTokensnumberMax output tokens (default 4096)
tierbudget \standard \premium \ultra \fable \kimiExplicit routing tier override (optional). Default: determined by skill context.
workTypeagentic-interactive \agentic-autonomous \frontend \backend \docs \chat \research \code-review \architecture \database \security \data-embeddings \summarize-extractDeclared work-type hint (plan/MULTI_PROVIDER_ORCHESTRATION.md §3) — resolves to the doc's intended primary engine + first-hop failover (optional).

SCHEDULES

schedules_list

List schedules sorted by nextRun. Filter by enabled, kind (agent|skill|tool), or last run status.

ParameterTypeDescription
enabledbooleanFilter by enabled flag (optional)
kindagent \skill \toolFilter by dispatch kind (optional)
statusnever \success \errorFilter by last run status (optional)
limitnumberMax results (default 100)

schedules_create

Create a new scheduled dispatch. kind=agent invokes a specialist via agents_invoke; kind=skill invokes a skill via skills_invoke; kind=tool dispatches an MCP tool directly with args parsed from the message field as JSON. Validates cron expression and computes nextRun.

ParameterTypeDescription
namestringHuman-readable name
cronExprstring5-field cron expression (min hour day month dow), e.g. "0 9 *" for 09:00 daily
kindagent \skill \toolDispatch kind: agent \skill \tool
targetstringAgent/skill/tool name to dispatch (e.g. solution-architect, code-review, morning_sweep)
messagestringFor agent/skill: the prompt. For tool: a JSON-encoded args object (e.g. '{"topN":3}')
repostringOptional repo for memory context (agent only)
includeMemoryContextbooleanInject repo memory context into the message (default false, agent only)
enabledbooleanWhether the schedule fires (default true)

schedules_update

Update a schedule by scheduleId. Recomputes nextRun if cronExpr changes. Pass only the fields you want to change.

ParameterTypeDescription
scheduleIdstringSchedule ID to update
namestring
cronExprstringNew cron expression — if changed, nextRun is recomputed from now
messagestring
repostring
includeMemoryContextboolean
enabledboolean

schedules_run_now

Dispatch a schedule immediately, bypassing nextRun. Updates lastRun/lastStatus but preserves the existing nextRun so the cron cadence is unaffected.

ParameterTypeDescription
scheduleIdstringSchedule ID to dispatch now

schedules_delete

Delete a schedule by scheduleId. Removes it permanently from the queue.

ParameterTypeDescription
scheduleIdstringSchedule ID to delete

schedules_seed

Idempotently seed the standard default schedules: morning_sweep_daily (09:00 UTC daily) and evening_sweep_daily (18:00 UTC daily), both kind=tool. Matches by name — never duplicates; schedules that already exist are left untouched and reported under "existing". Returns { created, existing, updated }.

ParameterTypeDescription
enabledbooleanWhether newly seeded schedules fire (default true)

RECURRING RUNNER TASKS (cron-cadenced queue templates)

recurring_tasks_list

List recurring runner-task templates sorted by nextFireAt. A recurring task re-enqueues a one-shot queue Task on a cron cadence (e.g. nightly state rotation, weekly dep-scan) instead of the operator re-adding one-shots. Distinct from schedules_list: schedules dispatch MCP tools/agents in-gateway; recurring tasks enqueue WORK for the CLI runner.

ParameterTypeDescription
enabledbooleanFilter by enabled flag (optional)
repostringFilter by target repo (optional)
limitnumberMax results (default 100)

recurring_tasks_create

Create a recurring runner-task template. On each cron fire the sweep enqueues a one-shot queue Task (source=scheduler, sourceId=recurringId) from this template for the CLI runner. Validates the cron expression and computes nextFireAt. overlapPolicy=skip (default) never enqueues while the previous instance is still open; overlapPolicy=stack always enqueues.

ParameterTypeDescription
namestringHuman-readable name (e.g. nightly_state_rotation)
cronExprstring5-field cron expression (min hour day month dow), e.g. "0 3 *" for 03:00 UTC nightly
repostringRepo the enqueued task targets
titlestringTitle for each enqueued one-shot task
descriptionstringTask description/details (optional)
priorityP0 \P1 \P2 \P3Priority for enqueued tasks (default P2)
assignedAgentstringSpecialist agent hint for enqueued tasks (optional)
recommendedModelstringModel hint for enqueued tasks (optional)
notesstringNotes carried onto each enqueued task (optional)
overlapPolicyskip \stackskip (default): do not enqueue while the previous instance is still open. stack: always enqueue.
enabledbooleanWhether the template fires (default true)

recurring_tasks_update

Update a recurring runner-task template by recurringId (e.g. toggle enabled, change cadence or the task template). Recomputes nextFireAt if cronExpr changes. Pass only the fields you want to change.

ParameterTypeDescription
recurringIdstringRecurring task ID to update
namestring
cronExprstringNew cron expression — if changed, nextFireAt is recomputed from now
repostring
titlestring
descriptionstring
priorityP0 \P1 \P2 \P3
assignedAgentstring
recommendedModelstring
notesstring
overlapPolicyskip \stack
enabledbooleanToggle the template on/off

recurring_tasks_run_now

Fire a recurring template immediately, enqueuing its one-shot task now while preserving the existing nextFireAt (the cron cadence is unaffected — mirrors schedules_run_now). Honors the template's overlapPolicy.

ParameterTypeDescription
recurringIdstringRecurring task ID to fire now

recurring_tasks_delete

Delete a recurring runner-task template by recurringId. Already-enqueued one-shot tasks are untouched.

ParameterTypeDescription
recurringIdstringRecurring task ID to delete

recurring_tasks_sweep

Recurring-task sweep (scheduler/recurring-task-sweep.ts): finds every due, enabled recurring template ACROSS ALL TENANTS and enqueues each as a one-shot queue Task under its own tenant, advancing nextFireAt per its cron. Designed to run as a frequent cron schedule (kind=tool, target=recurring_tasks_sweep — seeded as recurring_task_sweep_5min) or on demand.

No parameters.

ENTITLEMENTS (central plan-entitlement service, read-only)

entitlements_status

The single plan-entitlement snapshot for the calling tenant — Solo/Team/Scale feature gating + repo/seat/off-hours-minutes/generation-credit quota limits and current usage. Same computation as the dashboard's GET /api/entitlements (core/entitlement-service.ts, composing billing.ts's subscription gate + entitlements.ts's per-dimension caps) — the source of truth for "is this tenant entitled to do X", replacing ad-hoc plan checks. Read-only; never gated for the local operator.

No parameters.

BUDGETS (read-only)

budgets_status

Snapshot of the gateway LLM-spend budget: month-to-date and today's USD spend, configured caps, downgrade thresholds, and per-channel MTD breakdown when a per-channel cap is configured. Read-only. Returns zero spend with current config when budgets are disabled or MongoDB is unavailable.

No parameters.

budgets_breakdown

Spend breakdown by provider, model, and channel. Defaults to month-to-date (UTC). Pass from/to ISO timestamps to query a different window. Read-only.

ParameterTypeDescription
fromstringISO timestamp (UTC) for the start of the window. Defaults to start of current UTC month.
tostringISO timestamp (UTC) for the end of the window. Defaults to now.

budgets_suggestions

Learns from historical spend (BudgetUsage audit log) and SUGGESTS adjusted monthly/daily/per-channel caps — never auto-applies anything; caps stay env-driven. Each suggestion carries a recommendation (increase/decrease/keep/insufficient_data) and a rationale. Defaults to a 30-day lookback window; needs at least 7 distinct days of spend history to recommend a change. Read-only.

ParameterTypeDescription
lookbackDaysnumberHow many days of history to analyze. Defaults to 30.

ACCOUNT USAGE LEDGER (multi-Mac phase 2)

account_usage_record

Record per-ACCOUNT Claude/agy quota usage from one Mac (multi-Mac phase 2; plan/MULTI_MAC_SWARM_BRIEF.md). buckets: hourly token totals per account × host × model ({account, host, hour ISO, model, output, input, cacheCreate, cacheRead}) recomputed from that Mac's own transcripts (deduped by message.id) — upserted with $set, so re-pushing the same hour is idempotent. readings: REAL quota percentages ({account, host, source statusline|agy|operator, at, fiveHourPct, fiveHourResetsAt, sevenDayPct, sevenDayResetsAt, fablePct?, opusPct?}) from Claude Code's statusLine rate_limits, agy's quota file, or an operator /usage reading. assets: {account, kind full_reset|cloud_credit|spend_flag, usd?, expires?, active?, note?}. Pushed by scripts/usage_push.sh and scripts/usage_reading.sh. Distinct from usage_summary (product meter) and budgets_* (gateway LLM spend).

ParameterTypeDescription
bucketsobject[]Hourly token buckets (max 5000 per call).
readingsobject[]Real quota readings (max 200 per call).
assetsobject[]Account assets: banked full reset, cloud credit, spend flag (max 50).

account_usage_status

Per-ACCOUNT quota view across ALL Macs: 5-hour and weekly used % (source real = fresh statusLine/agy reading ≤15 min; anchored = last real reading + fitted cost of tokens since; estimate = fitted cost since the window reset; unknown), each account's own reset times, operator per-model rows (Fable/Opus), the least-squares fit (k = % per weighted token, n readings), weighted token totals (5h / 7d, per host), hot (an interactive session refreshed its statusLine ≤30 min ago), headroom after the interactive reserve (default weekly 33% / 5h 40%), assets, flags (e.g. usage credits on with no limit) and recommendations (banked full reset, expiring cloud credit) — recommendations only, nothing is ever triggered. Read-only.

ParameterTypeDescription
accountstringOnly this account (e.g. tech, personal, museum, agy).
reserveWeeklynumberInteractive reserve fraction for the weekly window (default 0.33).
reserveFiveHournumberInteractive reserve fraction for the 5-hour window (default 0.40).

USAGE METER (product events, read-only — ADR-014 S2)

usage_summary

Product-usage meter (UsageEvent): summed quantity per group key for the tenant. Unlike budgets_* (LLM spend), this counts billable product units — runner tasks executed, off-hours minutes, apps generated, agents invoked. Group by event type (default), day, or repo. Pass from/to ISO timestamps to bound the window (half-open [from, to)). Read-only; returns empty totals when metering is disabled or MongoDB is unavailable.

ParameterTypeDescription
fromstringISO timestamp — window start (inclusive).
tostringISO timestamp — window end (exclusive).
groupBytype \day \repoGroup key. Defaults to 'type'.

SWEEPS / REPORTS

morning_sweep

Daily autonomous sweep: rank managed repos by attention score, ask a specialist agent (default project-manager) for a short brief on each top repo, compose a markdown report, and optionally deliver via Telegram. Designed to run as a cron schedule (kind=tool, target=morning_sweep) or on demand.

ParameterTypeDescription
topNnumberHow many top-priority repos to brief (default 3)
agentstringSpecialist agent for the per-repo brief (default project-manager)
telegramChatIdstringTelegram chat ID to deliver the report to. Falls back to TELEGRAM_DEFAULT_CHAT env var if omitted.
briefMaxTokensnumberMax tokens per-repo agent brief (default 600)

evening_sweep

Daily evening summary: tasks completed today, LLM spend, repos worked on, and tomorrow's priority queue preview. Designed to run as a cron schedule (kind=tool, target=evening_sweep, e.g. "0 21 *" for 9pm) or on demand.

ParameterTypeDescription
telegramChatIdstringTelegram chat ID for report delivery (optional, falls back to TELEGRAM_DEFAULT_CHAT)
previewTopNnumberHow many repos to preview for tomorrow (default 3)

data_retention_purge

Compliance data-retention sweep: deletes terminal-state Task rows past TASK_RETENTION_DAYS (default 90), terminal-state PlanDay rows past PLAN_RETENTION_DAYS (default 180), and audit-log day-files past AUDIT_RETENTION_DAYS (default 400). Any tenant flagged legalHold=true is excluded entirely from every collection. Designed to run as a daily cron schedule (kind=tool, target=data_retention_purge) or on demand.

No parameters.

mrr_snapshot_sweep

Nightly MRR-snapshot job: persists one {tenantId, mrr, plan, capturedAt} document per non-deleted tenant for today (UTC), closing the gap where dashboard /revenue and /revenue/nrr could only read a single "now" MRR point per tenant. Idempotent — re-running the same UTC day upserts (overwrites) that day's row rather than duplicating it. Designed to run as a daily cron schedule (kind=tool, target=mrr_snapshot_sweep) or on demand.

No parameters.

erasure_sweep

GDPR/CCPA self-serve erasure sweep: finds every account-erasure request (core/account-erasure.ts) past its grace window (ERASURE_GRACE_DAYS, default 14) and irreversibly purges the tenant's scoped data, scrubbing the tenant row to a PII-free tombstone. Each request is handled independently — one tenant's purge failure never blocks the rest. Designed to run as a daily cron schedule (kind=tool, target=erasure_sweep) or on demand.

No parameters.

cancellation_purge_sweep

Billing-driven data-retention purge-on-cancel (core/tenant-lifecycle.ts): finds every tenant whose subscription-cancellation grace window (CANCELLATION_PURGE_GRACE_DAYS, default 30, started by the billing webhook on customer.subscription.deleted) has elapsed and irreversibly purges its scoped data — tasks/plans/schedules/directory cards/... (same collection set account-erasure.ts wipes) PLUS its audit trail — then scrubs the tenant row to a tombstone. Skips legal-hold tenants. Each tenant handled independently; one failure never blocks the rest. Designed to run as a daily cron schedule (kind=tool, target=cancellation_purge_sweep) or on demand.

No parameters.

tenant_suspend

Operator action: suspend a tenant (status=suspended), instantly blocking every gateway API-key call (auth.ts) for that tenant. Idempotent; refuses an already-deleted tenant. Uses targetTenantId (not tenantId) because executeTool() unconditionally strips an inbound tenantId — this tool genuinely targets a DIFFERENT tenant than the operator's own ctx.

ParameterTypeDescription
targetTenantIdstringTenant to suspend
reasonstringOptional free-text reason, recorded on the audit trail

tenant_reactivate

Operator action: restore a suspended tenant to status=active and clear any pending cancellation-purge schedule. Idempotent; refuses an already-deleted tenant. Uses targetTenantId (not tenantId) — see tenant_suspend.

ParameterTypeDescription
targetTenantIdstringTenant to reactivate

task_lease_reap

Task-lease reaper (tasks/task-store.ts reapStaleLeases): finds every task stuck in status=working whose leaseUntil has passed — the runner that claimed it died or was killed mid-task and nothing ever requeued the TASK itself (runner-lease-store's TTL index only reaps the SLOT lease, letting a new runner start, while the task document stays frozen). Releases each through the same failTask path a genuine runner failure uses, so retryCount/backoff/maxRetries→dead_letter semantics are identical. Designed to run as a frequent cron schedule (kind=tool, target=task_lease_reap) or on demand.

No parameters.

HEALTH / MONITORING

health_status

Comprehensive health check of the AI Management gateway and framework. Returns: gateway uptime, MongoDB connection status, vector corpus size, active schedules count, LLM provider status with resilience data (circuit breaker states, rate limiter stats), channel statuses, managed repo count, and memory usage. Use for production monitoring and debugging.

No parameters.

provider_health

Get detailed resilience health for LLM providers. Shows per-provider circuit breaker state (closed/open/half-open), failure/success counts, rate limiter token availability, total acquired/rejected tokens, and failover-chain data (inter-hop backoff config, hops attempted/succeeded-as-fallback, hops dropped for retry-budget/cost-budget). The "all providers" response (no provider filter) also includes the chain-wide configured retry budget (retryBudget.maxHops), the most recent dropped fallback hops (recentDroppedHops), and the live tier-router decision feed (recentRoutingDecisions — provider/model/reason for recent real LLM calls, newest first). Optionally filter to a single provider.

ParameterTypeDescription
providerstringOptional provider name to filter: api, deepseek, moonshot, ollama, bridge, direct

provider_reset

Manually reset a tripped circuit breaker for an LLM provider. Use when a provider has recovered but the circuit breaker has not timed out yet. Requires the provider name.

ParameterTypeDescription
providerstringProvider to reset: api, deepseek, moonshot, ollama, bridge, direct

provider_maintenance_enter

Operator-initiated: put an LLM provider into maintenance mode for planned work. Distinct from the circuit breaker (which trips automatically on errors) — this is a deliberate drain. In-flight calls are left to finish; the provider reports "draining" until they complete, then "maintenance". New calls for that provider queue behind the gate and fail over to the next provider in the mode chain (recoverable error), or resume once maintenance ends if there is no chain. Reflected in provider_health / health_status for a dashboard banner.

ParameterTypeDescription
providerapi \deepseek \moonshot \ollama \bridge \directProvider to place into maintenance: api, deepseek, moonshot, ollama, bridge, direct
reasonstringOptional operator-supplied reason (e.g. "planned DeepSeek maintenance window")
operatorstringOptional operator identity, for audit

provider_maintenance_exit

End an operator-initiated maintenance window for an LLM provider — resumes normal dispatch and immediately releases any calls queued behind the maintenance gate.

ParameterTypeDescription
providerapi \deepseek \moonshot \ollama \bridge \directProvider to resume: api, deepseek, moonshot, ollama, bridge, direct

fleet_maintenance_enter

Operator kill-switch: pause task claims for every runner across the whole fleet (all repos, all machines) — so the gateway can be safely deployed or autonomous work frozen without killing any runner process. A paused runner simply sees an empty queue on its next fire; nothing crashes or errors. Distinct from provider_maintenance_enter (drains one LLM provider) and per-tenant rate limiting (throttles volume, does not stop claims) — this is a hard stop on all claimTask calls fleet-wide. Idempotent: calling again while already active reschedules reason/operator/resumeAt in place. Optionally schedule an auto-resume with resumeAt (or resumeInMinutes) instead of requiring a manual fleet_maintenance_exit. Reflected in health_status for a dashboard banner.

ParameterTypeDescription
reasonstringOptional operator-supplied reason (e.g. "gateway redeploy")
operatorstringOptional operator identity, for audit
resumeAtstringOptional ISO-8601 timestamp to auto-resume at (schedulable maintenance window)
resumeInMinutesnumberOptional shorthand for resumeAt — auto-resume this many minutes from now

fleet_maintenance_exit

End the fleet-wide maintenance window immediately, resuming task claims for every runner. No-op-safe if the fleet was not paused.

No parameters.

ROUTING / DISPATCH

routing_info

Get the current LLM routing decision for a given context. Shows which provider and model would be selected for a specific tier, agent, channel, or tool. Useful for debugging routing decisions and understanding cost implications.

ParameterTypeDescription
tierbudget \standard \premium \ultra \fable \kimiExplicit routing tier (optional)
workTypeagentic-interactive \agentic-autonomous \frontend \backend \docs \chat \research \code-review \architecture \database \security \data-embeddings \summarize-extractDeclared work-type hint (plan/MULTI_PROVIDER_ORCHESTRATION.md §3) — takes priority over complexityLevel/tool/agent/channel, below an explicit tier (optional)
agentstringAgent name — affects tier selection (optional)
channelTypestringChannel type: telegram, scheduler, mcp, websocket (optional)
toolstringMCP tool name being executed (optional)
complexitynumberTask complexity score 0-1 (optional, >= 0.8 upgrades tier)
complexityLeveltrivial \low \standard \high \criticalNamed complexity bucket (plan/jam/multi-lane-distribution.md) — takes priority over agent/channel/tool (optional)
moderunner \interactiveExecution mode for complexityLevel resolution — defaults to runner for the scheduler channel, interactive otherwise (optional)

routing_config

Get the full routing configuration including tier definitions, agent-to-tier mappings, channel overrides, and tool routing rules. Read-only inspection of the LLM routing table for dashboards and debugging.

No parameters.

dispatch_cycle

Run one autonomous dispatch cycle: picks pending tasks from the queue, selects appropriate specialist agents, dispatches them, and reports results. Used by the scheduler for daily autonomous work or invoked manually. Respects budget caps.

ParameterTypeDescription
maxTasksnumberMax tasks to process in this cycle (default 3)
dailySpendCapUsdnumberSkip dispatch if daily spend exceeds this USD amount (optional)
telegramChatIdstringTelegram chat ID for progress notifications (optional)

inline_execute

In-gateway inline execution lane (ADR-018): run short deterministic pending tasks in-process via a whitelisted tool — no CLI-runner fire and no LLM spend. Only tasks carrying an explicit [inline:<op>] marker (op ∈ reprioritize, health, reindex, seed-schedules, usage-summary, repo-status) are eligible. Feature-flagged (INLINE_EXEC_ENABLED, default off → no-op) and quota-bounded (INLINE_EXEC_QUOTA per rolling window). Ineligible tasks are left for the CLI runner / dispatch worker.

ParameterTypeDescription
maxTasksnumberMax eligible tasks to run this cycle, 1-50 (default 10; also bounded by remaining quota)
repostringRestrict to one repo (optional)

FLEET / PATTERNS / STANDING AGENTS

fleet_overview

One-call fleet-wide dashboard: managed repo count + health summary, task queue totals by status, active schedule count, today's LLM spend, and top 3 repos needing attention. Ideal for Telegram status checks or quick session starts. Gracefully degrades if DB is unavailable.

No parameters.

pattern_analyze

Analyze SONA patterns from the memory/patterns/ store. Lists patterns with confidence scores, usage counts, and staleness (days since last used). Sorted by effectiveness (confidence × usageCount). Filter by category, tag, or minimum confidence threshold.

ParameterTypeDescription
categorystringFilter by pattern category (optional)
tagstringFilter by tag (optional)
minConfidencenumberMinimum confidence threshold 0–1 (default 0)
limitnumberMax results (default 20)

standing_agents_status

Status of all standing agent schedules: which standing agents are configured, their cron expressions, last run time/status, next run time, and whether they are enabled. Cross-references loaded agents against schedules; agents with no schedule are marked "unscheduled".

No parameters.

NOTIFICATIONS

notifications_send

Send a notification to one or more channels (Telegram, Discord, etc.). Formats the message with a level icon, optional title, and source tag. Falls back gracefully if a channel fails — never throws. Returns per-channel send results.

ParameterTypeDescription
messagestringThe notification content
channelsstring[]Channel types to send to (e.g. ["telegram", "discord"]). Defaults to all enabled channels.
chatIdstringSpecific chat/channel ID. Defaults to TELEGRAM_DEFAULT_CHAT or DISCORD_DEFAULT_CHANNEL env vars.
levelinfo \warning \error \criticalNotification level — prefixes with an icon (default: info)
titlestringOptional bold title line
sourcestringWhere the notification originated (e.g. webhook, health-alert, scheduler)

notifications_history

Retrieve recent notification history from the database. Returns an empty array if DB is not connected.

ParameterTypeDescription
limitnumberMax entries to return (default 20)

notifications_test

Send a test notification to verify channel connectivity. Sends "Test notification from myAI gateway" with level info.

ParameterTypeDescription
channelstringChannel to test (default: telegram)

HEALTH ALERTS

health_alerts_status

Get the latest health check result and alerting status. Returns the most recent HealthCheckResult (or null if never run), plus whether alerting is active, the check interval, dedup window, and tracked alert count.

No parameters.

health_alerts_run

Force an immediate health check cycle. Runs all probes (gateway, MongoDB, LLM providers, repos, scheduler, Docker), evaluates alert deduplication, and sends Telegram alerts for any degraded or unhealthy checks. Returns the full HealthCheckResult.

No parameters.

BRAIN (git-versioned agent memory — BRAIN B2)

brain_status

Brain store status: location, current branch, namespaces, atom counts (sessions/handoffs/memory), open session/idea branches, pending stashes, last commit. The brain is the git-versioned agent memory — sessions = commits, wrap up = merge, main = the consolidated truth agents boot from.

No parameters.

brain_health

Composite brain health index (BRAIN health-score): ONE 0-100 score + grade (excellent/good/fair/poor) rolling up freshness (days since last brain commit), coverage gaps (namespaces with atoms but no compiled brief/working yet), contradictions (divergent-brain merge/reconcile events in a trailing 30-day window), and recall hit-rate (the recall_session eval harness's tracked baseline, when one exists). Also returns the recent trend (recorded snapshots, one-per-hour throttled) so myai brain status and the dashboard can render a trend line. Distinct from per-atom recall analytics (most-recalled/staleness heatmap) — this is the one number to watch over time, not a breakdown.

ParameterTypeDescription
recordbooleanAppend a trend snapshot (default true, throttled to one per hour). Pass false for a read-only preview.

brain_recall_analytics

Per-atom recall analytics over the W3.3 live-recall telemetry log — the breakdown brain_health deliberately is NOT. Joins the recorded context_boot/brain_search/brain_delta recall events against a scan of the atom store and returns: most-recalled atoms (recall counts, per-tool split, chosen-vs-candidate, first/last recalled), a staleness heatmap (atom age × last-recall recency buckets, so "old but still recalled" separates from "old and cold"), and never-recalled DEAD atoms (unpinned, older than minDeadAgeDays) surfaced as a gc-actionable report: gc.candidatePaths carries repo-relative atom paths in exactly the BrainGcPlan format for brain gc / the operator to review and prune. Conservative by design — pinned atoms are never dead, fresh atoms are never dead, and an empty telemetry log yields zero candidates (no observations ≠ evidence of death). Read-only: telemetry log + directory walk; never mutates the brain.

ParameterTypeDescription
repostringScope the atom scan to one repo namespace (repos/<ns>/ only). Omit for the whole store including cross-repo memory/ atoms.
topLimitnumberMax most-recalled rows returned (default 20)
deadLimitnumberMax dead-atom detail rows returned (default 50); gc.candidatePaths is always the full list
minDeadAgeDaysnumberNever-recalled atoms younger than this many days are excluded from the dead list (default 14)

brain_manifest

Control-plane boot manifest (BRAIN B2): "know where what is without reading it." A tiny table-of-contents over the stores the 3-plane router dispatches against (brain-git, repo-sqlite-index, atlas-vectors — each with its fetch tools), this brain's namespaces (name + hasBrief/hasWorking + atom counts + lastAnchor, NO bodies), the cross-repo memory atom count, and freshnessSha (the brain main HEAD SHA to anchor a later brain_delta({since})). BRAIN-2: each namespace's lastAnchor is the SHA that repo's own last brain_merge landed at — pass it (or omit since entirely, since brain_delta({repo}) now defaults to it) for that repo's zero-file-read returning-boot catch-up. Extends ADR-020's tiered topic index one level up — which store/namespace to descend into, not which topic within one. Cheap by construction: directory listings + git rev-parse only, never an atom read.

No parameters.

brain_bandit_stats

Read-only snapshot of the BRAIN B-7 retrieval_bandit's current state (bandit_arms table): per query context, which retrieval config (k, rerank on/off) the bandit currently favors (argmax-exploit pick), the per-arm pull counts and mean reward backing that pick, and total pulls. Shells out to retrieval_bandit.py --summary against this repo's index DB — never mutates bandit_arms, unlike the offline replay_tune() pass. available:false when the repo has never been indexed (no state/.repo_index.sqlite3 yet) or the bandit has no recorded pulls.

No parameters.

brain_router_train_readiness

Router-training readiness (BRAIN B-7.1): labeled route-prediction traces banked (live route_eval rows with a resolved top-1 + the one-time harvested spike file) vs the 500-trace LoRA training floor, plus the trailing ingestion rate and ETA to that floor. Shells out to brain_router_train_ready.py --json against this repo's index DB — a readiness CHECK only: never trains, never writes (training stays gated/manual in train_router_lora.py). available:false when the repo has never been indexed (no state/.repo_index.sqlite3 yet).

No parameters.

brain_explore

Read-only browsable snapshot of the brain for the dashboard /brain explorer: namespaces with per-kind atom counts, a recent slice of the actual atoms (parsed frontmatter, newest first), open stashes with body previews, session/idea branches, recent commits, and the code↔memory provenance recorded on HEAD. Pure inspection — never checks out, merges, or writes.

ParameterTypeDescription
atomLimitnumberMax recent atoms to return (default 60, cap 200)
sectionsstring[]Which EXPENSIVE sections to compute — one per dashboard tab. Omit for all (default). Namespaces, totals, branches, recent commits and the open-stash count are always returned; these three cost per-atom reads or extra git calls, so an off-tab load can skip them (e.g. [] for Overview, ["provenance"] for the provenance tab).

brain_commit

Commit one append-only memory atom to the brain on the current branch. Atoms are immutable — identical re-writes dedup to a no-op; changed content becomes a NEW atom. kind=memory atoms are cross-repo (omit repo); session/handoff atoms live under their repo namespace (auto-created). Pass topic (ADR-020: a controlled tag — runner-ops, cost-policy, gateway-infra, go-live, continuity, distribution, billing, brain, security, docs — extensible) so the atom is indexed into the GOLD/SILVER topic hierarchy; omitting it defaults to 'general' and returns a lint warning. Pass supersedes (slug or sha8 of a prior atom) to RETIRE that atom from the hot path — the structural fix for ACTION-section bloat (no keep-last-N cap); the superseded atom stays in history (rollup/BRONZE). Pass code_* to stamp code↔memory provenance (BRAIN B5). kind=session atoms also get a non-blocking quality lint — the atom still commits; check lint.warnings and prompt for enrichment if non-empty.

ParameterTypeDescription
kindsession \handoff \memoryAtom kind: session block, handoff entry, or cross-repo memory fact
repostringProject namespace (required for session/handoff; omit for cross-repo memory)
slugstringShort human label — slugified into the filename
contentstringThe atom body (markdown)
topicstringADR-020 topic tag (controlled set: runner-ops, cost-policy, gateway-infra, go-live, continuity, distribution, billing, brain, security, docs — extensible). Missing → 'general' + a lint warning.
supersedesstringADR-020: slug or sha8 of a prior atom this one replaces. Retires it from the GOLD/SILVER hot path (stays in rollup/BRONZE history).
pinbooleanMark this atom load-bearing at write time: the distiller NEVER drops it (exempt from supersession retirement, near-dup collapse, and budget cuts — renders in the dedicated pinned section of brief/working), and recall ranking never age-decays it. Pin an EXISTING atom with brain_pin instead.
code_repostringProvenance: code repo name (defaults to repo)
code_branchstringProvenance: code branch the work happened on (e.g. test)
code_shastringProvenance: code HEAD SHA at write time
code_commitsstring[]Provenance: code commit SHAs this session produced

brain_observe

Append one raw observation record to the zero-LLM ring-buffer capture buffer (BRAIN W1.1/W1.4) — the MCP-tool twin of the hooks/post-tool/07-brain-observe.sh PostToolUse hook, for agents that don't run Claude Code hooks (Gemini/Codex/opencode connected via myai connect-agent). Same JSONL shape, same per-repo/per-session file, same bounded rotation — one buffer, fed from either path, so no connected agent's session is silently lost. This is scratch capture, NOT a committed atom: it is never git-added and is not a substitute for brain_commit — a future distiller folds it into real atoms.

ParameterTypeDescription
repostringProject namespace (matches the repo folder name the hook uses — same string lands on the same buffer file)
sessionstringCaller session id. Omit to fall back to an hour-bucketed key (imperfect but distinct across concurrent callers).
toolstringName of the tool call being observed
targetstringShort description of what was acted on (path, command, query, …) — truncated to 300 chars
exitok \error \unknownOutcome of the observed call (default: unknown)
filesstring[]Files touched by the observed call, if known

brain_stash

Freeze a context payload and walk away: the stash is committed to the brain's MAIN branch (not the session branch), so ANY later session — different agent, device, or branch — can brain_pop it and resume. Not git-stash: it survives across processes and machines.

ParameterTypeDescription
slugstringShort label to pop it by later
contentstringThe frozen context (markdown): what you were doing, next steps, open questions
repostringProject this context belongs to (optional)

brain_pop

Pop the newest brain stash (or the newest one matching slug): returns the frozen context and removes the entry from main with a normal commit. Use after brain_status shows pending stashes.

ParameterTypeDescription
slugstringPop the newest stash with this slug (default: newest of all)

brain_pin

Pin a load-bearing EXISTING atom (by content sha8 or repo-relative atom path) so the distiller NEVER drops it: pinned atoms are exempt from supersession retirement, near-duplicate collapse, and budget-driven omission — they render first in a dedicated "pinned" section of brief.md (GOLD) and working.md (SILVER) — and recall ranking never age-decays them. The pin is a tiny registry marker committed to brain main (pins/<sha8>.md); the atom itself stays immutable. Content-addressed: every atom sharing the sha8 is pinned. Idempotent; throws if no such atom exists on main. New atoms can be pinned at write time via brain_commit's pin flag instead.

ParameterTypeDescription
refstringAtom content sha8 (the 8-hex filename tail) or repo-relative atom path (memory/… or repos/<ns>/{sessions,handoffs}/…)

brain_unpin

Remove a never-drop pin (by atom sha8 or path): deletes the pins/<sha8>.md registry marker from brain main with a normal commit. The atom itself is untouched — it simply becomes subject to normal distiller compaction (supersession, near-dup collapse, budget cuts) and recall age-decay again.

ParameterTypeDescription
refstringAtom content sha8 (8 hex chars) or atom path whose pin to remove

brain_branch

Create or resume a brain branch. kind=idea (default): long-lived parallel thinking context idea/<slug> off main. kind=session: today's auto session branch session/<date>-<host>-<slug> (slug acts as the profile, e.g. cli).

ParameterTypeDescription
slugstringIdea slug (idea/<slug>) or session profile (default cli)
kindidea \sessionBranch family (default: idea)

brain_checkout

Check out an existing brain branch: main, session/<...> or idea/<...>. Refuses unknown refs and anything outside those families.

ParameterTypeDescription
refstringBranch to check out (main \session/* \idea/*)

brain_merge

Merge a session or idea branch into main (--no-ff) — what wrap-up calls. Session branches are deleted after the merge; idea branches survive (long-lived). Defaults to the CURRENT branch. Conflicts abort cleanly and leave the branch unmerged. BRAIN-2: also stamps the resulting main SHA as the delta anchor (lastAnchor) for every repo namespace this merge touched — surfaced in brain_manifest/context_boot and used automatically by a later brain_delta({ repo }) call that omits since.

ParameterTypeDescription
branchstringBranch to merge (default: current branch)

brain_log

Brain commit history (newest first): sha, date, subject. Scope with ref (branch/sha) and/or path (e.g. repos/<name>/sessions).

ParameterTypeDescription
refstringBranch or commit to log from (default: HEAD)
pathstringLimit to a path inside the brain (optional)
limitnumberMax commits (default 20, cap 200)

brain_diff

What changed between two brain refs (default main..HEAD — what the current session has that main doesn't). Returns changed files + shortstat; pass patch=true for the unified diff (truncated at 20k chars).

ParameterTypeDescription
fromstringBase ref (default: main)
tostringTarget ref (default: HEAD)
pathstringLimit to a path inside the brain (optional)
patchbooleanInclude the unified patch (default false)

brain_delta

Diff-only catch-up: "what changed in the brain since <sha>?" Pass the last-seen brain main SHA (since, remembered from a previous boot/delta) to get ONLY the delta — new atoms (content, capped), commits, and which compiled artifacts changed — a ~300-800 token payload instead of a full re-boot. BRAIN-2: since is optional when repo is scoped — omit it and the gateway resolves it itself from lastAnchor, the SHA that repo's own last brain_merge landed at (also readable up front via brain_manifest/context_boot), so a returning boot needs zero file reads and zero client-side SHA bookkeeping. No since and no stored anchor (this repo's first merge) degrades to the blank-agent path: the compiled ~150-token boot brief. Remember the returned sha as the next anchor if you want to pass it explicitly next time. Scope with repo to one namespace (+ cross-repo memory/). Pass topic (the session's actual working topic, an ADR-020 BRAIN_TOPICS slug) to rank returned atoms GOLD/SILVER/BRONZE-then-topic-match before falling back to recency — so an atom on an unrelated topic can't crowd a same-topic atom out of the budget.

ParameterTypeDescription
sincestringLast-seen brain main SHA (optional when repo is set — defaults to that repo's stored lastAnchor; omit both for the blank-agent brief path)
repostringScope to one repo namespace + cross-repo memory/ (optional) — also gates the since-omitted lastAnchor default
budgetnumberChar budget for atom contents (default 3200 ≈ 800 tokens). The per-atom cap scales with it — max(900, budget/2) — so a larger budget returns a long wrap atom (and its trailing ACTION block) whole instead of a 900-char head.
topicstringSession's current working topic (ADR-020 slug) — prioritizes topic-matched atoms in the returned order (optional)

brain_lookup

Traverse the ADR-020 topic index instead of scanning it. Reads GOLD (the ~150-tok brief TOC), matches topic (exact) or query against the namespace's topic branches, and returns ONLY the matched SILVER section(s) — never loads branches that didn't match (O(1) root + O(1) branch, not O(n) over the whole namespace). No match → GOLD + the availableTopics list so you can pick a branch (never blank). query matching: when BRAIN_LOOKUP_EMBED=1, scores the query against topic-branch embeddings first (confidence-floored) so a paraphrase with no literal term overlap can still land the right branch; falls back to plain string/tag matching otherwise or when nothing clears the confidence floor. Use this for "what's the current X policy" lookups instead of grepping the archive.

ParameterTypeDescription
repostringRepo namespace to look up within (required)
querystringFree-text query — tag/term matched against topic names and section text
topicstringExact topic branch to descend into (skips query matching)

brain_blame

Code↔memory provenance lookup (BRAIN B5). Forward: pass code_sha (full or ≥7-char prefix) to find the brain commits whose provenance stamps reference that code commit — "what was the agent thinking when it produced commit X", with the atom files (session logs) to read. Reverse: pass ref (a brain branch/commit, e.g. idea/<slug>) to list every code SHA its commits recorded — "what code did this line of thinking produce". Stamps come from brain_commit code_* args.

ParameterTypeDescription
code_shastringCode commit SHA (or ≥7-char prefix) to trace back to brain commits
refstringBrain ref (branch/commit) to list recorded code SHAs for (default HEAD; mutually exclusive with code_sha)
limitnumberMax entries (default 50, cap 200)

brain_entity

Cross-session ENTITY recall — "what changed about X" (BRAIN B10). A lightweight, deterministic temporal/entity layer over the brain (Graphiti-style: entities + time-stamped "touched" edges, extracted by plain regex — NO per-write LLM, no embeddings, no new storage). Pass query to get the entity records whose name matches (case-insensitive substring): each returns its timestamped touches with a snippet from every atom that mentioned it, so you can read what changed each time and when. Omit query to list the most-recently-touched entities (a map of what the brain knows). Entity kinds: repo (namespace), file (path mentioned), feature (atom slug + tag-style names), person (@mention), decision (ADR-*). Scope with repo and/or kind. The verbatim atoms stay the source of truth — this is an augmenting index, computed on read.

ParameterTypeDescription
querystringEntity name to recall (substring, case-insensitive). Omit for the recently-touched map.
kindrepo \file \feature \person \decisionRestrict to one entity kind (optional)
repostringScope to one repo namespace + cross-repo memory/ (optional)
limitnumberMax entity records (default 20, cap 200)
touchLimitnumberMax touches per entity (default 25, cap 200)
atomLimitnumberMax recent atoms scanned (default 800, cap 5000)

brain_timeline

Cross-session TEMPORAL recall — "when did I last touch Y" / recent activity (BRAIN B10). The time-ordered feed over the same lightweight entity index as brain_entity. Pass entity to get that entity's "touched" edges newest-first plus its first/last-touched timestamps — the direct answer to "when did I last touch Y". Omit entity for the recent cross-entity activity feed (optionally scoped by kind/repo) — a temporal overview of what has been worked on lately. Use since (a raw UTC stamp like 20260706T234100Z, e.g. a previous lastTouched) to get only newer events. Deterministic + extractive; augments the verbatim atoms, never replaces them.

ParameterTypeDescription
entitystringEntity to trace (substring, case-insensitive). Omit for the recent-activity feed.
kindrepo \file \feature \person \decisionRestrict to one entity kind (optional)
repostringScope to one repo namespace + cross-repo memory/ (optional)
sincestringOnly events strictly after this UTC stamp (YYYYMMDDTHHMMSSZ) (optional)
limitnumberMax events (default 40, cap 500)
atomLimitnumberMax recent atoms scanned (default 800, cap 5000)

brain_communities

GraphRAG-style GLOBAL/THEMATIC recall — "what's been going on with the auth area" without knowing which entity to ask about (BRAIN B-6, the community-summary half of B10 Graphiti: plan/BRAIN_BUILD_PLAN.md day 8). Builds a timestamped entity co-occurrence graph over the same deterministic entity extraction as brain_entity/brain_timeline (two entities edge-connect when an atom mentions both), runs Leiden-style community detection (Louvain modularity optimization + a connectivity-refinement pass), and returns each community as a compact extractive summary — top entities, repos, active time window, and top co-occurrence edges (each with firstSeen/lastSeen) — largest/most-active first. Pass query to filter to communities whose summary or member entities match (substring, case-insensitive) — a thematic search over the community layer instead of scanning every atom. Deterministic + LLM-free, computed on read; augments the verbatim atoms, never replaces them.

ParameterTypeDescription
querystringThematic filter: match against community summaries/entity names (substring, case-insensitive). Omit for all communities.
repostringScope to one repo namespace + cross-repo memory/ (optional)
minSizenumberMinimum entities per community to include (default 2, cap 50)
limitnumberMax communities returned (default 20, cap 200)
atomLimitnumberMax recent atoms scanned (default 800, cap 5000)

brain_revert

Undo a brain commit with an inverse commit — history is never rewritten (atoms stay append-only). Merge commits revert against their first parent. Conflicts abort cleanly, leaving the brain unchanged.

ParameterTypeDescription
shastringCommit to revert

Federated recall: one ranked query across this tenant's brain atoms (sessions, handoffs, and cross-repo memory facts — every repo namespace) AND the RAG session corpus (STATE.md/handoff/archive vectors — every repo) at once. Distinct from per-namespace sharing/read-only grants (which expose ONE namespace to another tenant) — this unions and ranks what one tenant already owns across its OWN multiple repo-brains, so "what have we done about X" doesn't require knowing which repo holds the answer. Omit repo to federate across all of them; pass it to narrow to one.

ParameterTypeDescription
querystringNatural language or keyword search query
repostringNarrow to one repo namespace instead of federating across all (optional)
knumberMax merged results (default 10, cap 100)
sincestringISO date (YYYY-MM-DD) — only recall session-corpus vectors on or after this date (optional; atoms are unaffected)
atomLimitnumberMax recent atoms scanned per the brain-atom side (default 500, cap 5000)

brain_namespace_share

Grant another tenant scoped access to ONE of this tenant's brain namespaces (the bare namespace name — internally stored under repos/<namespace>, but pass just <namespace>). Role-gated: configure. level is read (browse only) or read-write (browse + append atoms). Re-sharing with the same granteeTenantId updates the level and clears any prior revocation — one active grant per (namespace, grantee). Distinct from team-brain (whole-team sharing); this is a single owner→grantee grant, typically cross-tenant.

ParameterTypeDescription
namespacestringThe bare namespace name to share (e.g. a repo name) — NOT prefixed with "repos/"
granteeTenantIdstringThe tenant being granted access
levelread \read-writeAccess level to grant

brain_namespace_unshare

Revoke a previously granted namespace access. Role-gated: configure. The grant record is kept with revokedAt set (an audit trail, not a delete) — see brain_namespace_grants. Throws if the grantee never held a grant on this namespace; a no-op if already revoked.

ParameterTypeDescription
namespacestringThe bare namespace name to revoke access to — NOT prefixed with "repos/"
granteeTenantIdstringThe tenant whose access is being revoked

brain_namespace_grants

The access list for one of this tenant's namespaces — every grant ever issued (active and revoked), newest first. Role-gated: read. Pass activeOnly to filter out revoked grants.

ParameterTypeDescription
namespacestringThe bare namespace name to list grants for — NOT prefixed with "repos/"
activeOnlybooleanFilter out revoked grants (default false)

brain_namespace_read

Read a namespace another tenant (ownerTenantId) has shared with THIS tenant: the compiled boot brief plus recent session/handoff atoms and counts. Requires an active grant of at least read on (ownerTenantId, namespace) — enforced at the gateway boundary against the caller's own server-derived tenant identity. Reads only the owner's main branch (the consolidated truth), never an in-progress session branch.

ParameterTypeDescription
ownerTenantIdstringThe tenant that owns and shared the namespace
namespacestringThe shared bare namespace name — NOT prefixed with "repos/"
limitnumberMax recent atoms per kind to return (default 5, cap 50)

brain_namespace_write

Append a session/handoff atom into a namespace another tenant (ownerTenantId) has shared with THIS tenant at read-write level. Requires an active read-write grant on (ownerTenantId, namespace) — a read-only grant is refused. The atom is committed into the owner's brain, attributed to this tenant in both the frontmatter (shared-write-by) and the git commit author.

ParameterTypeDescription
ownerTenantIdstringThe tenant that owns and shared the namespace
namespacestringThe shared bare namespace name — NOT prefixed with "repos/"
kindsession \handoffAtom kind
slugstringShort human label — slugified into the filename
contentstringThe atom body (markdown)

brain_host_provision

Provision (or adopt) this tenant's HOSTED brain remote — a managed, gateway-served, tenant-scoped git repo the brain pushes to, so users who won't self-host git get turnkey cross-device continuity (ADR-017). Gated on the plan's hosted-brain entitlement (Pro/Team; free tier is refused). Returns the remote URL and a one-time access token (the token is never persisted — store it now; use brain_host_rotate to reissue). Point the brain at it once with brain init --remote <url> / git remote set-url origin <url>; sync is invisible thereafter. Self-host remains the default (data-locality).

No parameters.

brain_host_status

This tenant's hosted brain remote status (ADR-017): whether provisioned, the display remote URL (no credential), plan, created/rotated timestamps, encryption-at-rest posture, and quota (used vs plan cap). No secret material is returned.

No parameters.

brain_host_rotate

Rotate this tenant's hosted brain access token (ADR-017) — mints a fresh token and invalidates the old one (leak response / reissue). Returns the new remote URL + one-time token; update the brain's origin URL to match.

No parameters.

brain_template_publish

Publish one immutable version of a STARTER-BRAIN pack (operator only): a curated bundle of brain atoms (domain conventions, common patterns) new tenants seed their brain from instead of starting cold. Versions are strict X.Y.Z semver and immutable — a re-publish of an existing version is refused (fix forward: bump the version). Atom topics are normalized warn-only (ADR-020); non-blocking nudges come back in warnings. Distinct from brain backup/restore (a tenant's OWN data) and from marketplace packages (agents/skills) — this is brain CONTENT templating.

ParameterTypeDescription
idstringPack identity slug, stable across versions (e.g. nextjs-saas)
versionstringStrict X.Y.Z semver — immutable once published
titlestringHuman-readable pack title
descriptionstringWhat domain baseline this pack seeds
atomsobject[]Curated atoms (max 200, 1 MB total content). Each: {kind: session\handoff\memory, repo? (required for session/handoff), slug, topic?, content}

brain_template_list

Browse the starter-brain pack catalog — every operator-published pack with its latest version, all published versions, and atom count. Pair with brain_template_get to inspect a pack's atoms, and brain_seed to seed this tenant's brain from one.

No parameters.

brain_template_get

Fetch one published starter-brain pack (latest version unless version is pinned) including its full curated atoms — inspect what a brain_seed would write before running it.

ParameterTypeDescription
idstringPack id (from brain_template_list)
versionstringSpecific X.Y.Z version; defaults to the latest published

brain_seed

Seed THIS tenant's brain from a published starter pack — the new-tenant bootstrap that replaces an empty store with a curated domain baseline. Creates the (tenant-scoped, ADR-010) brain repo if missing, writes every pack atom through the ordinary append-only path (content-hash dedup — nothing is ever overwritten), and records a marker memory atom (pack@version) so re-seeding the same version is an idempotent no-op. Refused once the brain has real session history (pass force:true to layer a pack onto a lived-in brain anyway). Distinct from brain backup/restore: this seeds CURATED shared content, not the tenant's own data.

ParameterTypeDescription
packstringPack id to seed from (see brain_template_list)
versionstringSpecific X.Y.Z version; defaults to the latest published
forcebooleanSeed even though the brain already has session history (default false)

brain_seed_status

Which starter packs already seeded this tenant's brain (parsed from the marker atoms brain_seed writes): pack id, version, and when — the provenance/audit view of seeding.

No parameters.

marketplace_publish

Submit a marketplace package for review (ADR-019 Implementation checklist #2). Accepts the same pack()-shaped marketplace.manifest.json body a future myai-marketplace CLI would produce (ADR-028 §2) and re-runs its four submission checks SERVER-SIDE, fail-fast in order — schema validity (incl. manifestHash integrity against the submitted artifact bytes), declaredTools ⊆ the marketplace-exposable tool allowlist (ADR-028 §5), semver/immutability rules (ADR-028 §4 — no re-publish of an already-published version), and an injection-pattern scan mirroring the security-integrity agent's scan. Any local CLI validation is advisory-fast only; this is the actual security boundary (ADR-028 §3). On a pass, uploads the artifact bytes to the ADR-029 artifact store's staging/ keyspace under a content-addressed key derived from manifestHash, re-verifies the round-tripped bytes hash (ADR-029 §4), and creates or refreshes an in_review ListingVersion row with that real artifactUri, returning it plus any non-blocking scan warnings. On failure (including a failed artifact upload/integrity re-check), returns a structured rejection naming which check failed and why — never throws for an ordinary validation failure.

ParameterTypeDescription
manifestobjectThe pack()-shaped marketplace.manifest.json body (ADR-028 §2), schema: architecture/schemas/marketplace-package-manifest.schema.json
artifactContentstringRaw content of the packaged artifact (agent.md, or the concatenated skill/ tree) — used for the manifestHash integrity check and the injection-pattern scan; never persisted as artifact bytes.

Browse the published marketplace catalog (ADR-019 Implementation checklist #2) — free-text match against title/summary/slug/tags, optionally narrowed by kind (agent|skill) and/or category. Only published listings are discoverable (ADR-019 §3 listing-lifecycle); draft/in_review/suspended/delisted listings never appear. Currently served against the local filesystem artifact backend (ADR-029 §2's self-hosted default) — the S3/CDN production backend is a later swap-in behind the same catalog, not a blocker. Returns catalog summaries only (no install action taken); pair with marketplace_install to install a result by slug.

ParameterTypeDescription
qstringFree-text query matched against title, summary, slug, category, and tags (case-insensitive substring)
kindagent \skillRestrict to agents or skills
categorystringExact category match
limitnumberMax results to return (default 20, cap 100)

marketplace_install

Install a published marketplace listing by slug for the caller's tenant (ADR-019 Implementation checklist #2). Requires the listing published AND the target version published — not yanked (the ADR-019 §3 install gate). Before completing, re-fetches the version's artifact bytes from the ADR-029 local filesystem artifact backend and re-verifies sha256(bytes) === manifestHash (ADR-029 §4 fetch-integrity re-check) — a mismatch or missing artifact fails closed with no install created. One live install per tenant per listing (reinstall requires uninstalling first — not yet exposed by this tool). Free listings only for now: one_time/subscription/usage pricing requires the billing checkout flow (dashboard /api/marketplace/checkout), not this tool — a paid listing returns a structured rejection rather than a silent free install.

ParameterTypeDescription
slugstringThe listing slug to install (from marketplace_search results)
versionstringSpecific semver to pin; defaults to the listing's latest published version

plugin_tools_register

Register (or update, upsert-by-name) a CUSTOM MCP tool for the caller's tenant (task-6f9ae8ea) — name + JSON-Schema input contract + an HTTPS handler URL the gateway proxies tools/call to with a per-plugin timeout, extending the built-in tool surface at runtime without a redeploy. ENV-GATED, off by default (MYAI_TENANT_TOOL_PLUGINS=1); strictly tenant-scoped (a plugin never appears in another tenant's tools/list); a plugin can never shadow a built-in tool (registration refuses colliding names, and built-ins win at dispatch). handlerUrl must be https (http for loopback only); timeoutMs is clamped to [250, 30000] (default 10000); max 20 plugins per tenant. Every registry change is audited (plugintool.change) and every proxied invocation is audited (plugintool.invoke). Requires the configure capability (admin+), same rung as connectors_set / webhook management.

ParameterTypeDescription
namestringTool name, snake_case 3-64 chars ([a-z][a-z0-9_]{2,63}); must not collide with a built-in tool
descriptionstringWhat the tool does — shown verbatim in tools/list
schemaobjectThe tool's MCP inputSchema (JSON Schema; type must be "object")
handlerUrlstringHTTPS endpoint the gateway POSTs {tool, arguments, tenantId} to (http allowed only for loopback)
timeoutMsnumberPer-call proxy timeout in ms, clamped to [250, 30000]; default 10000
enabledbooleanRegister disabled (hidden from tools/list, refuses dispatch); default true

plugin_tools_list

List the caller tenant's registered custom MCP tool plugins (plugin_tools_register) — name, description, inputSchema, handler URL, timeout, enabled flag, timestamps. Returns an empty list when the plugin system is env-gated off (MYAI_TENANT_TOOL_PLUGINS unset) or nothing is registered. Registry view only — the enabled subset is what tools/list appends after the built-in surface.

No parameters.

plugin_tools_remove

Remove one of the caller tenant's custom MCP tool plugins by name (see plugin_tools_register / plugin_tools_list). The tool disappears from tools/list immediately and further calls to it fall through to the normal Unknown-tool error. Audited (plugintool.change). Requires the configure capability (admin+). Env-gated like the rest of the plugin system.

ParameterTypeDescription
namestringThe registered plugin tool name to remove