Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
Control APIs

Control HTTP API

Current public MuBit control-plane HTTP routes for memory, context, diagnostics, coordination, and explicit planning state.

This page documents the current public HTTP control surface. In application code, prefer the helper-first SDK methods where they exist and use these routes as wire-contract and debugging references.

Core memory routes

RouteMethodPurposeRecommended SDK surface
/v2/control/ingestPOSTAsync ingest for facts, traces, lessons, rules, WM, and other typed memoryremember() for normal writes, raw client.ingest(...) when you need job control
/v2/control/batch_insertPOSTCompatibility bulk write pathraw client.batchInsert(...) / batch_insert(...)
/v2/control/ingest/jobs/:job_idGETIngest job status and completionraw client.getIngestJob(...) / get_ingest_job(...)
/v2/control/queryPOSTAnswer-oriented routed retrievalrecall() or raw client.query(...)
/v2/control/contextPOSTPre-assembled context block with disclosure modes and budget controlgetContext() / get_context()
/v2/control/activityPOSTChronological memory/activity browse surface with scope and type filtersHTTP / gRPC only — no SDK helper
/v2/control/activity/exportPOSTExport chronological memory/activity as JSONLdirect HTTP or operator export tooling
/v2/control/archivePOSTWrite an exact reusable artifact block and return a stable reference_idarchive() / archive_block()
/v2/control/dereferencePOSTFetch exact stored content by reference_iddereference()
/v2/control/diagnosePOSTFailure-path lesson surfacingdiagnose()
/v2/control/memory_healthPOSTMemory quality, staleness, contradictions, and section healthmemoryHealth() / memory_health()
/v2/control/reflectPOSTExtract lessons and rules from run evidencereflect()
/v2/control/lessonsPOSTList stored lessons for a run/session scoperaw client.lessons(...)
/v2/control/lessons/deletePOSTDelete a stored lessonforget() or raw lesson delete
ℹ️Note

/v2/control/ingest and /v2/control/batch_insert accept at most 1000 items per request; larger requests return HTTP 400 (InvalidArgument). Chunk bigger writes client-side.

MAS and learning-loop routes

RouteMethodPurposeRecommended SDK surface
/v2/control/agentsPOSTList registered agents for the runlistAgents() / list_agents()
/v2/control/agents/registerPOSTRegister an agent identity and its scopesregisterAgent() / register_agent()
/v2/control/checkpointPOSTSave a pre-compaction or pre-transition checkpointcheckpoint()
/v2/control/outcomePOSTReinforce a lesson or rule after success/failure/partial outcomerecordOutcome() / record_outcome()
/v2/control/step_outcomePOSTRecord a per-step process reward signal within a runrecordStepOutcome() / record_step_outcome()
/v2/control/strategiesPOSTSurface repeated patterns from stored lessons and rulessurfaceStrategies() / surface_strategies()
/v2/control/handoffPOSTPersist a coordination handoff between agentshandoff()
/v2/control/feedbackPOSTPersist a response to a handoff or review requestfeedback()

Explicit planning and state routes

⚠️Warning

The goals, actions, and decision-cycle routes are deprecated — track tasks in your orchestration framework (LangGraph, CrewAI) or a task system (Linear, Jira) and persist only the resulting lessons and outcomes in MuBit. The variables and concepts routes remain supported. All of these are HTTP/gRPC-only — none are exposed as typed SDK helpers. See State management.

RouteMethodPurpose
/v2/control/goals/addPOSTAdd a goal
/v2/control/goals/updatePOSTUpdate a goal
/v2/control/goals/listPOSTList goals
/v2/control/goals/treePOSTRetrieve the nested goal tree
/v2/control/variables/setPOSTSet an explicit run-scoped variable
/v2/control/variables/getPOSTGet a variable
/v2/control/variables/listPOSTList variables
/v2/control/variables/deletePOSTDelete a variable
/v2/control/concepts/definePOSTDefine a concept
/v2/control/concepts/listPOSTList concepts
/v2/control/actions/submitPOSTRecord an action
/v2/control/actions/logPOSTRead the action log
/v2/control/cycles/runPOSTRecord a reasoning / planning cycle
/v2/control/cycles/historyPOSTRead cycle history

Run management and agent lifecycle routes

RouteMethodPurposeRecommended SDK surface
/v2/control/runsGETList recent runsclient.control.listRunHistory(...) / client.advanced.list_run_history(...)
/v2/control/runs/linkPOSTLink a child run to a parent runraw client.linkRun(...) / link_run(...)
/v2/control/runs/unlinkPOSTUnlink a previously linked runraw client.unlinkRun(...) / unlink_run(...)
/v2/control/delete_runPOSTDelete a run and its associated dataraw client.deleteRun(...) / delete_run(...)
/v2/control/agents/heartbeatPOSTAgent liveness heartbeat signalraw client.agentHeartbeat(...) / agent_heartbeat(...)
/v2/control/activities/appendPOSTAppend an activity record to a runHTTP / gRPC only — no SDK helper
/v2/control/context/snapshotPOSTFull context snapshot including working memory and attentionclient.control.contextSnapshot(...) / client.advanced.context_snapshot(...)
/v2/control/events/subscribeGETStream control events via SSEraw client.subscribe(...)
/v2/control/ingest/statsPOSTGet per-run ingest statisticsraw client.getRunIngestStats(...) / get_run_ingest_stats(...)

Operating guidance

  • Prefer helper methods for normal application code.
  • Use raw route-level control when you need exact request-shape control, ingest-job polling, or contract debugging.
  • Treat /v2/control/context as the default compaction-safe context assembly surface for long-running systems.
  • Treat /v2/control/activity as the chronological audit surface for stored MuBit data. It is separate from semantic query.
  • Use /v2/control/archive plus /v2/control/dereference when later steps need exact artifact fidelity rather than only semantic discovery.
  • Use diagnose, memory_health, and strategies before changing prompts blindly.

Temporal query parameters

POST /v2/control/query and POST /v2/control/context accept temporal filtering and budget control:

FieldTypeRequiredDescription
min_timestampint64noLower bound for temporal filter (unix seconds, inclusive). Filters by occurrence_time with created_at fallback.
max_timestampint64noUpper bound for temporal filter (unix seconds, inclusive).
budgetstringnoSearch budget tier: "low", "mid" (default), "high". Controls latency/quality tradeoff.

Staleness fields in query evidence

Evidence items in query and context responses may include staleness metadata:

FieldTypeDescription
is_staleboolWhether this entry has been superseded by a newer version
superseded_bystringID of the superseding entry (empty if not stale)

Stale entries are returned with a ranking penalty. Filter them in your application if you only want current information.

Occurrence time on ingest

POST /v2/control/ingest items accept an occurrence time field:

FieldTypeRequiredDescription
occurrence_timeint64noWhen the event actually occurred (unix seconds). Distinct from ingestion time. Used for temporal queries and recency ranking.

Evidence provenance and context pressure

/v2/control/query and /v2/control/context now expose reuse provenance on surfaced evidence:

  • retrieval_mode: semantic, exact_reference, checkpoint, rule_overlay, lesson_overlay, or working_memory
  • reference_id: stable exact-reference ID when available
  • referenceable: whether the source can be dereferenced later
  • origin_entry_type: typed LTM source such as fact, lesson, rule, archive_block, or checkpoint

The /v2/control/query response also includes a citations array — 0-based indices into evidence marking which items grounded final_answer (empty when the answer cites no specific evidence or was an abstention). Indices are validated server-side against the evidence length, so every value is a valid index into evidence. Use them to render citations or audit answer grounding.

/v2/control/context also reports context-pressure telemetry:

  • requested token budget
  • budget_used
  • budget_remaining
  • source counts by entry type
  • source counts by retrieval mode
  • evidence_candidates_considered
  • evidence_dropped_by_budget
  • exact_references_surfaced

Run-level outcome request shape

POST /v2/control/outcome reinforces a lesson or rule after a success/failure/partial outcome. Beyond the core fields (reference_id, outcome, signal, rationale, agent_id, user_id, verified_in_production), the wire request accepts two attribution fields:

FieldTypeRequiredDescription
entry_idsstring[]noAdditional contributing memory entry IDs for multi-entry attribution. Each is resolved within the run and scope-checked; unknown or out-of-scope IDs are skipped. The primary reference_id is never double-counted if it also appears here
idempotency_keystringnoClient-supplied dedup token. When set, the outcome is applied at most once for the token — a retry with the same key (e.g. after a transport timeout) returns success WITHOUT re-applying the signal, so reinforcement counts aren't double-counted. A wire-level field; it is not exposed on the record_outcome() SDK helper

Step-level outcome request shape

POST /v2/control/step_outcome records a per-step process reward signal, complementing the run-level /v2/control/outcome.

FieldTypeRequiredDescription
run_idstringyesSession/run identifier
step_idstringyesUnique step identifier within the run
step_namestringnoHuman-readable step label
outcomestringyesOne of success, failure, partial, neutral
signalfloatnoReward signal from -1.0 to 1.0
rationalestringnoWhy this outcome was assigned
directive_hintstringnoHindsight guidance for future runs
agent_idstringnoAgent that performed the step
user_idstringnoLogical user scope
metadata_jsonstringnoArbitrary JSON metadata

Response: { "step_outcome_id": "...", "accepted": true }.

Use after each agentic step where you want dense reward signal. To produce step-attributed lessons, set include_step_outcomes on the reflect request. This is a wire-level ReflectRequest field (not a kwarg on the Python reflect() helper): send it via the raw control surface, e.g. client.advanced.reflect({"run_id": ..., "include_step_outcomes": True}) (Python) or client.control.reflect({ run_id, include_step_outcomes: true }) (JS).

Lane parameters

Lanes partition memory within a shared run for multi-agent isolation.

RouteFieldDescription
/v2/control/ingestlane (on each item)Tags ingested items with a named lane
/v2/control/querylane_filterRetrieves only entries tagged with the specified lane
/v2/control/contextlane_filterFilters context assembly by lane
/v2/control/agents/registershared_memory_lanesDeclares which lanes an agent participates in

Items without a lane are visible to all queries. Items with a lane are visible only when lane_filter matches or is empty.

ℹ️Note

lane (MAS memory isolation) is distinct from the core data-plane retrieval lane concept used in direct search routing. See Core Direct Lanes for the data-plane concept.

Step-wise reflection parameters

POST /v2/control/reflect now accepts additional fields for targeted reflection:

FieldTypeDescription
step_idstringScope reflection to a specific step
last_n_itemsint32Reflect only over the N most recent evidence items
include_step_outcomesboolInclude recorded step outcomes as reflection input

These compose with existing fields (run_id, checkpoint_id). Use last_n_items for incremental after-each-step reflection, and include_step_outcomes when step reward signals should influence lesson extraction.

Activity routes request shapes

POST /v2/control/activity

List chronological memory/activity entries.

FieldTypeRequiredDescription
run_idstringnoSession/run scope. When empty, lists activity across runs visible to the actor
user_idstringnoLogical user scope
agent_idstringnoFilter by agent
entry_typesstring[]noFilter by entry type (e.g. ["fact", "lesson"])
created_afterstringnoInclusive lower-bound timestamp (RFC3339)
created_beforestringnoInclusive upper-bound timestamp (RFC3339)
sortstringno"desc" (default, newest first) or "asc"
limituint32noPage size. Defaults to 100 and is clamped to [1, 500] — an omitted or 0 limit resolves to 1, not 100
page_tokenstringnoOpaque pagination cursor returned as next_page_token from the previous page (currently a numeric offset string)
exclude_derivedboolnoWhen true, exclude promoted/derived facts from the listing
projectionstringno"full" (default) or "compact" (truncates content to 200 chars and strips verbose metadata)

Response: { "entries": [...], "next_page_token": "...", "total_visible": int }. next_page_token is empty when the last page has been reached.

POST /v2/control/activity/export

Export activity as JSONL.

FieldTypeRequiredDescription
run_idstringyesSession/run identifier
formatstringnoExport format, default "jsonl"
entry_typesstring[]noFilter by entry type

Response: JSONL stream of activity entries.

POST /v2/control/activities/append

Append manual activity traces.

FieldTypeRequiredDescription
run_idstringyesSession/run identifier
entriesobject[]yesActivity entries to append
entries[].typestringyesEntry type (e.g. "observation", "action")
entries[].contentstringyesEntry content
agent_idstringnoAgent that produced the entries

Response: { "appended": int }.

Run management request shapes

POST /v2/control/runs/link

FieldTypeRequiredDescription
run_idstringyesParent run identifier
linked_run_idstringyesChild run to link

Response: { "linked": true }.

POST /v2/control/runs/unlink

FieldTypeRequiredDescription
run_idstringyesParent run identifier
linked_run_idstringyesChild run to unlink

Response: { "unlinked": true }.

POST /v2/control/delete_run

FieldTypeRequiredDescription
run_idstringyesRun to delete

Response: { "deleted": true }.

POST /v2/control/context/snapshot

FieldTypeRequiredDescription
run_idstringyesSession/run identifier
include_working_memoryboolnoInclude working memory state
include_goalsboolnoInclude active goals

Response: { "snapshot": { "working_memory": {...}, "attention": {...}, "goals": [...] } }.

POST /v2/control/ingest/stats

FieldTypeRequiredDescription
run_idstringyesSession/run identifier

Response: { "total_ingested": int, "by_type": {...}, "last_ingest_at": string }.

GET /v2/control/ingest/jobs/:job_id

No request body. Returns:

FieldTypeDescription
job_idstringJob identifier
statusstringOne of pending, processing, completed, failed
items_totalintTotal items in the job
items_processedintItems processed so far
created_atstringISO timestamp
completed_atstringISO timestamp (if completed)

Managed resources: Projects, Agents, Skills, Prompts

Managed MuBit deployments expose a resource model so you can configure agents declaratively instead of re-encoding them in every run. Projects group related agents, each agent owns a versioned system prompt and a set of skills (tools/playbooks), and all of it is versioned with a candidate → active promotion flow.

Project CRUD

RouteMethodPurposeRecommended SDK surface
/v2/control/projectsPOSTCreate a projectclient.createProject(...) / create_project(...)
/v2/control/projects/listPOSTList projectsclient.listProjects(...) / list_projects(...)
/v2/control/projects/getPOSTGet a single projectclient.getProject(...) / get_project(...)
/v2/control/projects/updatePOSTRename / describeclient.updateProject(...) / update_project(...)
/v2/control/projects/deletePOSTDelete a projectclient.deleteProject(...) / delete_project(...)

POST /v2/control/projects request:

FieldTypeRequiredDescription
namestringyesProject name (shown in the console)
descriptionstringnoShort description

Response: { "project": { "project_id": "proj-...", "name": "...", "description": "...", "agent_ids": [], "created_at": "...", "updated_at": "..." } }.

Agent Definition CRUD

Agents belong to a project and own a role, description, and active system prompt.

RouteMethodPurpose
/v2/control/projects/agentsPOSTCreate agent definition
/v2/control/projects/agents/listPOSTList agents in a project
/v2/control/projects/agents/getPOSTGet a single agent
/v2/control/projects/agents/updatePOSTUpdate role / description / prompt
/v2/control/projects/agents/deletePOSTDelete an agent

POST /v2/control/projects/agents request:

FieldTypeRequiredDescription
project_idstringyesOwning project
agent_idstringyesStable agent identifier
rolestringnoShort role description
descriptionstringnoLonger description
system_prompt_contentstringnoInitial prompt — creates the first active PromptVersion

Run history for a project

RouteMethodPurpose
/v2/control/projects/runsPOSTList run history for a project
/v2/control/projects/runs/getPOSTGet a specific run history record

Run history records expose lessons_extracted, prompt_changes, avg_outcome_score, outcome_count, and ingest_count per run — so you can observe how an agent's behavior evolves.

Prompt versioning + optimization

Every agent has at most one active PromptVersion and zero or more candidate PromptVersions awaiting approval. The control plane can mint candidates automatically via optimize_prompt.

RouteMethodPurpose
/v2/control/prompt/setPOSTWrite a new version (activate=true promotes immediately)
/v2/control/prompt/getPOSTGet the current active prompt
/v2/control/prompt/versionsPOSTList all versions for an agent
/v2/control/prompt/activatePOSTPromote a candidate to active
/v2/control/prompt/optimizePOSTLLM-powered candidate generation from recent outcomes
/v2/control/prompt/diffPOSTDiff two versions (returns unified diff_text)

Version statuses: active, candidate, retired, archived. Sources: manual, optimization, rollback.

POST /v2/control/prompt/optimize request:

FieldTypeRequiredDescription
agent_idstringyesAgent whose prompt is being optimized
project_idstringyesContaining project
llm_overrideobjectno{ provider, model, temperature, max_tokens, timeout_ms }. timeout_ms is clamped server-side to [1000, 600000] ms (10 min); out-of-range values are silently adjusted

Response: { success, candidate, optimization_summary, confidence, activated }.

Skill CRUD + optimization

Skills are named tools or playbooks attached to a project (or optionally to a specific agent). They version identically to prompts.

RouteMethodPurpose
/v2/control/skillsPOSTCreate skill
/v2/control/skills/listPOSTList skills
/v2/control/skills/getPOSTGet a skill
/v2/control/skills/updatePOSTUpdate definition
/v2/control/skills/deletePOSTDelete a skill
/v2/control/skills/versionsPOSTList versions
/v2/control/skills/activatePOSTPromote a candidate skill version
/v2/control/skills/optimizePOSTGenerate a candidate skill version from recent outcomes
/v2/control/skills/diffPOSTDiff two skill versions

POST /v2/control/skills request:

FieldTypeRequiredDescription
project_idstringyesOwning project
agent_idstringnoIf set, attaches the skill to a specific agent
namestringyesSkill name
descriptionstringnoShort description
parameters_schemastringnoJSON schema describing parameters
instructionsstringnoInstructions/playbook text
skill_typestringno"tool" (default) or "playbook"

Control sessions

Sessions are long-lived handles the control plane uses to coordinate multi-turn agent work. In typical SDK usage, run_id serves the same purpose; sessions are exposed for tools that need explicit lifecycle control.

RouteMethodPurpose
/v2/control/sessions/createPOSTCreate a control session
/v2/control/sessions/getPOSTFetch session state (phase, ingest count, last activity)
/v2/control/sessions/closePOSTClose a session

Platform health endpoints

These unauthenticated routes live at the root of each MuBit node (alongside /v2/core/* and /v2/control/*). Use them for Kubernetes probes, load-balancer checks, and operational monitoring — not from application code.

RouteMethodPurposeTypical use
/livezGETLiveness: the process is running and its HTTP stack is responsive. Always returns 200 while the server accepts connections.Kubernetes livenessProbe; triggers pod restart on failure. Keep the threshold forgiving — a busy node should not be killed.
/readyzGETReadiness: the node is ready to serve real traffic. Returns 503 while background ACL and sparse-index rebuilds are still running (reads would see stale state in that window).Kubernetes readinessProbe and load-balancer health check; a 503 temporarily removes the node from rotation without restarting it.
/v2/core/healthGETCoarse legacy health probe. Unauthenticated. Returns the literal string "OK" when the HTTP layer is up.External checks that only need "is the endpoint reachable". Prefer /livez + /readyz for K8s.
/metricsGETPrometheus scrape endpoint — includes mubit_llm_calls_total, mubit_llm_tokens_total, mubit_llm_call_duration_seconds, storage and ingest counters.Prometheus / Grafana scraping.

GET /livez

Response: 200 OK with body ok.

Liveness is intentionally cheap. It does not query storage, Redis, or any downstream dependency — that is the job of /readyz. A failing /livez means the process is wedged and should be restarted.

GET /readyz

Responses:
  • Ready: 200 OK
    { "status": "ready" }
  • Not ready: 503 Service Unavailable
    { "status": "not_ready", "reason": "acl_rebuild_in_progress" }

The node flips to ready once the initial ACL warmup, sparse-index prewarm, and partitioned sparse prewarm complete. During that window, the process accepts connections (so /livez stays 200) but returns 503 from /readyz so the load balancer can route around it.

Typical reason values: starting, acl_rebuild_in_progress, sparse_prewarm_in_progress. Treat reason as a diagnostic hint — it is advisory, not API-stable.

ℹ️Note

The platform-api service (which fronts the console and the managed-instance API) exposes its own /healthz on port 8080. That is a separate surface from the data-plane /livez//readyz probes above, which sit on each instance's port 3000.

Next steps