Sessions
Create, observe, update, and stop persistent agent work.
Sessions bind an immutable agent snapshot to an environment and own an append-only event history.
SDK and HTTP example
This excerpt uses the client and resources from Quickstart. Select your language; the wire contract and lifecycle rules follow below.
const session = await client.sessions.create({ agent: agent.id, environment_id: environment.id, title: 'First session' });Create
POST /v1/sessions
The agent field supports three forms.
Latest version:
{
"agent": "agent_...",
"environment_id": "env_...",
"title": "Investigation"
}Pinned version:
{
"agent": {"type": "agent", "id": "agent_...", "version": 2},
"environment_id": "env_..."
}Session-local overrides:
{
"agent": {
"type": "agent_with_overrides",
"id": "agent_...",
"version": 2,
"system": "Focus on production incidents.",
"tools": []
},
"environment_id": "env_..."
}Overrides replace model, system, tools, MCP servers, or skills for this session
only. They do not mutate or renumber the agent. A model override may change the
model ID or speed; effort remains an Agent-level setting and a session override
does not replace it. Overrides also apply to self copies in a coordinator
roster. Independently referenced Agents are unaffected.
For a coordinator, session.agent.multiagent.agents expands the Agent
resource's Version references into full immutable Agent definitions. The
definitions are captured with the Session, in roster order, rather than loaded
again when a child Thread starts. A self definition reflects the effective
Session overrides and every roster member omits its own multiagent field,
preserving the one-level topology. Existing Sessions keep those snapshots even
if a referenced Agent is later updated or archived.
The effective custom Skill list is revalidated when the Session is created.
Every omitted or latest value is replaced by a concrete immutable Version in
the returned session.agent.skills snapshot. PostgreSQL pins those Versions in
the same transaction as the Session; deleting a pinned Version is rejected
until the Session is physically deleted. Up to 500
unique scope-pinned Skills are accepted across the primary and complete roster,
subject to one 500 MiB aggregate expanded-size limit and unique runtime names
per execution scope. The self-hosted worker verifies pinned archives and exposes
them below its skills/ workdir; roster Agents use isolated subdirectories
below skills/.agents/. The model first receives every Skill name plus
descriptions bounded to one percent of the configured context window.
When it invokes the private Skill dispatcher, the runtime returns
Launching skill: <name> and injects the complete selected SKILL.md, prefixed
with its base directory, into the provider conversation. Referenced supporting
files remain on disk for ordinary read or bash access. Self-hosted workers
download the same immutable primary and roster pins before tool dispatch,
verify each canonical archive's advertised byte length and SHA-256 digest, and
add a 500 MiB compressed-byte plus 10,000-file Session guard; the
server-side Agent loop reads the main instruction entry directly from Mango's
canonical archive rather than reaching into the worker filesystem. Their
model-visible skills/... paths are relative to the worker's configured
workdir. See Sandboxes for the execution boundary.
Optional initial_events may contain up to 50 user.message or
user.define_outcome objects. A non-empty list starts execution immediately.
An outcome may use either an inline text rubric or a ready File rubric
from the same Workspace. File text is validated and snapshotted before the
Session admission transaction, so a missing or invalid File cannot leave a
partially created Session and deleting it later cannot change the active
outcome.
The optional title, metadata, initial_events, resources, and vault_ids
fields must use their documented non-null shapes when present; omission supplies
the empty/default value. budget: null explicitly selects no spend ceiling. A
non-null budget sets a Session-wide ceiling in integer USD cents:
{
"budget": {
"type": "limit",
"max_list_cost": {"amount": "2500", "currency": "USD"}
}
}Budgeted Sessions require model IDs present in Mango's built-in price catalog,
which currently contains canonical Anthropic model IDs and published list
prices, for the coordinator and every resolved roster member. A router may
still forward those requests, but an opaque router-defined model alias is not
assigned a guessed price.
resources accepts up to eight Memory Store inputs:
{
"type": "memory_store",
"memory_store_id": "memstore_...",
"access": "read_write"
}A Memory Store input uses memory_store_id, optional instructions, and
read_write or read_only access. It can only be attached at creation. The
self-hosted worker prepares it below /mnt/memory. File and Git inputs are not
part of Mango's self-hosted contract; stage them in the operator-owned workspace.
vault_ids is an ordered list of active Vault references. The order is frozen
with the Session: for an MCP endpoint, the first Vault containing a matching
credential wins. Admission requires the Vault keyring to be configured and
rejects missing, archived, empty, or duplicate references. Updating
vault_ids after creation remains unsupported by the current Mango contract.
Get and update
GET /v1/sessions/{id}
POST /v1/sessions/{id}The update body accepts agent, metadata, title, and budget:
{
"title": "New title",
"metadata": {"owner": "sre", "stale": null},
"agent": {
"tools": [
{"type": "agent_toolset_20260401"},
{"type": "mcp_toolset", "mcp_server_name": "linear"}
],
"mcp_servers": [
{"type": "url", "name": "linear", "url": "https://mcp.linear.app/sse"}
]
}
}metadatais a per-key patch: a string upserts the key,nulldeletes it, and omitting the field preserves the whole bag.titlemay be omitted or set to a string;nullis not a no-op update.agentupdates onlytoolsandmcp_servers, as a full replacement: the array you send becomes the new value,[]clears, and omitting preserves.model,system, andskillsare fixed for the session's lifetime and are rejected; set them withagent_with_overridesat create time instead.- An
agentupdate is session-local. It never renumbers or mutates the agent resource, and it applies from the next turn. - An
agentupdate requires anidlesession. A request that arrives while a turn is in flight returns409; send an untargeteduser.interruptfirst.titleandmetadatacarry no such precondition. vault_idsis rejected on update by the current Mango API.- A Session created with a budget may replace it or set
budget: nullto remove it. A changed maximum must be strictly greater than the exact list cost already consumed. A Session created without a budget cannot add one later, and a removed budget cannot be re-added.
Changed fields and their session.updated event commit together. The event
carries only the fields the request actually changed; a request that changes
nothing emits no event.
List
GET /v1/sessions
Supported query parameters:
| Parameter | Meaning |
|---|---|
limit | Page size, 1–1000; default 100. Values above 1000 return a validation error. |
order | asc or desc; default desc |
page | Opaque next or previous cursor |
agent_id | Match agent ID |
agent_version | Match version; requires agent_id |
statuses[] | Repeatable public status filter |
include_archived | true or false |
created_at[gt|gte|lt|lte] | RFC 3339 timestamp bounds |
deployment_id | Match Sessions created by the Deployment |
memory_store_id | Match Sessions attached to the Memory Store |
The response includes both directions:
{
"data": [],
"next_page": null,
"prev_page": null
}Archive and delete
POST /v1/sessions/{id}/archive
DELETE /v1/sessions/{id}A running session cannot be archived or deleted and returns 409. A
user.interrupt durably cancels active model or tool Activities across API and
worker processes so the Session can return to idle. Omitting
session_thread_id interrupts every non-archived Thread; providing it targets
only the named Thread.
Archive prevents further input and retains history and Session Files, but does not release the sandbox. Automatic idle or archive-based sandbox reclamation is not implemented. Delete performs sandbox cleanup and removes Session-owned Files; download any outputs you need to retain before deleting a Session.
Delete removes the session and persisted history, sends a final
session.deleted event to active subscribers, and closes their streams:
{"id": "session_...", "type": "session_deleted"}Response notes
The response embeds the resolved agent snapshot and includes nullable budget,
resources, vault_ids, outcome_evaluations, stats, usage, and
deployment_id.
stats and usage are cumulative live projections, and
outcome_evaluations reflects each admitted outcome. resources embeds active
File and Memory Store Resource objects. Ordered vault_ids are resolved at
creation; update-time vault replacement is rejected.
usage aggregates provider-reported token, prompt-cache, Web Fetch, and Web
Search counters across every Session Thread. usage.list_cost is calculated
from Mango's current built-in price catalog, provider-reported execution facts
that affect that catalog's rates, the Web Search request rate, and $0.08 per
Session active hour, then rounded to the nearest cent for the public monetary
projection. Provider routing is not Agent configuration. Thread list cost
excludes Session runtime. Accounting remains exact internally, and
model-request admission checks the shared ceiling before every request; an
already in-flight request may take the Session over its limit.
Provider-reported tokens remain visible even when a response-level billing rule
makes their list cost zero, such as an unbilled Claude Fable 5 refusal.
When the ceiling is reached, affected Threads become idle with
budget_reached. If the whole Session becomes idle, session.usage is emitted
immediately before session.status_idle. A pending client action takes
precedence as requires_action; its result remains admissible, and the budget is
checked before any subsequent model request. Raising or removing the budget
resumes a turn that was paused at that check.
deployment_id is null for direct Session creation and contains the parent
Deployment ID for Deployment-created Sessions.
Worker workspace files remain operator-owned and are not automatically published through the Files API.