MCP catalogs
Artifacts, memory, and handoffs
Exact arguments and input schemas for artifacts, memory, and handoffs.
On this page
arc_create_artifact
Create a durable artifact (doc, spec, summary, table…) in a room. kind=table|checklist|form|pixel-grid render natively in the desktop and echo edits back as notices — body schemas: arc_get_hub_info().typed_artifact_kinds. Bodies are capped at max_artifact_chars (hub-info states the live value; split longer content into indexed parts). Returns a compact receipt — sha256, body_chars, saved_to (project › room; quote it when telling the operator where the work lives) — never a body echo. To store an existing local file, pass body_path instead of body.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | yes | string | See the schema below. |
title | yes | string | See the schema below. |
kind | yes | string | See the schema below. |
body | no | string | See the schema below. |
body_path | no | string | absolute path to a UTF-8 text file to store verbatim as the body (mutually exclusive with body; read by this bridge process with your own file permissions) |
by_agent_id | no | string | See the schema below. |
metadata | no | object | See the schema below. |
tags | no | array | See the schema below. |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string"
},
"title": {
"type": "string"
},
"kind": {
"type": "string"
},
"body": {
"type": "string"
},
"body_path": {
"type": "string",
"description": "absolute path to a UTF-8 text file to store verbatim as the body (mutually exclusive with body; read by this bridge process with your own file permissions)"
},
"by_agent_id": {
"type": "string"
},
"metadata": {
"type": "object"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"room_id",
"title",
"kind"
]
}arc_update_artifact
Edit an artifact in place (title/body/tags replace, metadata shallow-merges; the daemon bumps metadata.revision and stamps updated_at/updated_by/sha256). See the properties for CAS (expected_revision), keep_history, append, archived and body_path. Returns a receipt, never the body.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
artifact_id | yes | string | See the schema below. |
title | no | string | See the schema below. |
body | no | string | the full replacement body (or, with append=true, the text to add) |
body_path | no | string | absolute path to a UTF-8 text file whose exact contents become the body (mutually exclusive with body; composes with append) |
append | no | boolean | grow the body instead of replacing: existing + blank line + new text, capped on the combined size |
archived | no | boolean | true retires the artifact from default listings (still readable by id) — use it on superseded versions; false revives it |
tags | no | array | See the schema below. |
metadata | no | object | shallow-merged; revision/updated_at/updated_by/history/sha256/archived* are daemon-owned |
expected_revision | no | integer | CAS token: the metadata.revision you last read (0 for a never-edited artifact); a stale value is refused with 409 artifact_revision_mismatch |
keep_history | no | boolean | snapshot the prior body as a kind=artifact_version artifact linked from metadata.history (auto-archived, never crowds listings) |
by_agent_id | no | string | attribution override (defaults to you) |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"artifact_id": {
"type": "string"
},
"title": {
"type": "string"
},
"body": {
"type": "string",
"description": "the full replacement body (or, with append=true, the text to add)"
},
"body_path": {
"type": "string",
"description": "absolute path to a UTF-8 text file whose exact contents become the body (mutually exclusive with body; composes with append)"
},
"append": {
"type": "boolean",
"description": "grow the body instead of replacing: existing + blank line + new text, capped on the combined size"
},
"archived": {
"type": "boolean",
"description": "true retires the artifact from default listings (still readable by id) \u2014 use it on superseded versions; false revives it"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"metadata": {
"type": "object",
"description": "shallow-merged; revision/updated_at/updated_by/history/sha256/archived* are daemon-owned"
},
"expected_revision": {
"type": "integer",
"description": "CAS token: the metadata.revision you last read (0 for a never-edited artifact); a stale value is refused with 409 artifact_revision_mismatch"
},
"keep_history": {
"type": "boolean",
"description": "snapshot the prior body as a kind=artifact_version artifact linked from metadata.history (auto-archived, never crowds listings)"
},
"by_agent_id": {
"type": "string",
"description": "attribution override (defaults to you)"
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"artifact_id"
]
}arc_move_artifact
Move an artifact into another room of the same project (the reconciliation verb when two rooms diverged): artifact.moved lands in both rooms, metadata.moved_from records the origin. Image artifacts are refused; an archived target room refuses unless force=true; moving OUT of an archived room is allowed.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
artifact_id | yes | string | See the schema below. |
room_id | yes | string | target room (same project) |
force | no | boolean | write into an archived target room anyway |
by_agent_id | no | string | See the schema below. |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"artifact_id": {
"type": "string"
},
"room_id": {
"type": "string",
"description": "target room (same project)"
},
"force": {
"type": "boolean",
"description": "write into an archived target room anyway"
},
"by_agent_id": {
"type": "string"
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"artifact_id",
"room_id"
]
}arc_copy_artifact
Duplicate an artifact into another room; the copy's metadata.copied_from points back at the source. Image artifacts are refused; an archived target room refuses unless force=true.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
artifact_id | yes | string | See the schema below. |
room_id | yes | string | target room |
force | no | boolean | See the schema below. |
by_agent_id | no | string | See the schema below. |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"artifact_id": {
"type": "string"
},
"room_id": {
"type": "string",
"description": "target room"
},
"force": {
"type": "boolean"
},
"by_agent_id": {
"type": "string"
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"artifact_id",
"room_id"
]
}arc_list_artifacts
Compact artifact index for your joined room (or room_id): artifact_id, title, kind, size_bytes, tags, metadata, a one-line preview, and a fetch hint — never the bodies. Use it to answer 'what is already saved in this room?' in one small call; read one record with arc_get_artifact(artifact_id). Filter with kind, tags, since (ISO lower bound), or limit (newest n). Pass detail=full only when every body is genuinely needed — a 40-artifact room is ~200K characters that way. Archived artifacts (and auto-archived artifact_version history snapshots) are excluded unless include_archived=true.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | no | string | explicit room override; defaults to the joined room |
detail | no | string | default summary (no bodies) Allowed: summary, full. |
kind | no | string | exact kind filter, e.g. doc, memory, table |
tags | no | array | every listed tag must be present |
since | no | string | ISO timestamp; only artifacts created at or after it |
limit | no | integer | keep only the newest n (still returned oldest first) |
include_archived | no | boolean | include retired artifacts and history snapshots (default false) |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string",
"description": "explicit room override; defaults to the joined room"
},
"detail": {
"type": "string",
"enum": [
"summary",
"full"
],
"description": "default summary (no bodies)"
},
"kind": {
"type": "string",
"description": "exact kind filter, e.g. doc, memory, table"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "every listed tag must be present"
},
"since": {
"type": "string",
"description": "ISO timestamp; only artifacts created at or after it"
},
"limit": {
"type": "integer",
"description": "keep only the newest n (still returned oldest first)"
},
"include_archived": {
"type": "boolean",
"description": "include retired artifacts and history snapshots (default false)"
}
},
"required": []
}arc_get_artifact
Read one Arc artifact by artifact_id. Budgeted by default: the body comes back in a max_chars window (default 24000) and result.body_range names {offset, returned_chars, total_chars, next_offset} — when next_offset is non-null, call again with offset=next_offset to continue; a small artifact simply arrives whole. kind="image" artifacts return the text twin (alt/description + sha256) as the body; vision-capable managed seats additionally receive the image pixels with the result, while other agents work from the twin.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
artifact_id | yes | string | See the schema below. |
max_chars | no | integer | body window budget in characters; default 24000, floor 500 |
offset | no | integer | character offset to resume from (a prior result's body_range.next_offset) |
Complete input schema
{
"type": "object",
"properties": {
"artifact_id": {
"type": "string"
},
"max_chars": {
"type": "integer",
"description": "body window budget in characters; default 24000, floor 500"
},
"offset": {
"type": "integer",
"description": "character offset to resume from (a prior result's body_range.next_offset)"
}
},
"required": [
"artifact_id"
]
}arc_search
Search messages, decisions, artifacts, and skills for a substring; case-insensitive, thin summaries rather than bodies. Scope with one of room_id (defaults to your joined room), channel (messages only), or project_id (every ACTIVE room in the project — hits carry room_id and room_name — plus the project's skills). Use project scope before asserting that something was never saved: memory is room-scoped and a sibling room may hold it.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
query | yes | string | substring to search for |
types | no | array | optional subset of content types; defaults to every type in scope (channel scope: messages only) |
room_id | no | string | room scope; defaults to your joined room |
channel | no | string | optional channel scope (messages only) |
project_id | no | string | optional project scope: messages, decisions, artifacts across the project's active rooms, and its skills |
limit | no | integer | max total results (default 50) |
Complete input schema
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "substring to search for"
},
"types": {
"type": "array",
"items": {
"type": "string",
"enum": [
"message",
"decision",
"artifact",
"skill"
]
},
"description": "optional subset of content types; defaults to every type in scope (channel scope: messages only)"
},
"room_id": {
"type": "string",
"description": "room scope; defaults to your joined room"
},
"channel": {
"type": "string",
"description": "optional channel scope (messages only)"
},
"project_id": {
"type": "string",
"description": "optional project scope: messages, decisions, artifacts across the project's active rooms, and its skills"
},
"limit": {
"type": "integer",
"description": "max total results (default 50)"
}
},
"required": [
"query"
]
}arc_remember
Store a durable agent-memory item in an Arc room. Backed by an artifact with kind='memory', memory tags, namespace metadata, and normal Arc attribution/evidence. Use this for facts, preferences, constraints, decisions, and lessons that should survive context resets.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | yes | string | room that owns this memory |
title | no | string | short retrieval-friendly title; generated from body when omitted |
body | yes | string | concise memory text: what future agents need to know and why |
namespace | no | string | short memory namespace, e.g. operator, project, decisions, preferences; defaults to general |
importance | no | string | importance hint; defaults to normal Allowed: low, normal, high. |
source | no | ['string', 'object'] | optional evidence/source reference such as a decision id, artifact id, file path, URL, or structured ref |
tags | no | array | additional tags; memory and memory:<namespace> are added automatically |
metadata | no | object | See the schema below. |
by_agent_id | no | string | attribution override (defaults to you) |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string",
"description": "room that owns this memory"
},
"title": {
"type": "string",
"description": "short retrieval-friendly title; generated from body when omitted"
},
"body": {
"type": "string",
"description": "concise memory text: what future agents need to know and why"
},
"namespace": {
"type": "string",
"description": "short memory namespace, e.g. operator, project, decisions, preferences; defaults to general"
},
"importance": {
"type": "string",
"enum": [
"low",
"normal",
"high"
],
"description": "importance hint; defaults to normal"
},
"source": {
"type": [
"string",
"object"
],
"description": "optional evidence/source reference such as a decision id, artifact id, file path, URL, or structured ref"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "additional tags; memory and memory:<namespace> are added automatically"
},
"metadata": {
"type": "object"
},
"by_agent_id": {
"type": "string",
"description": "attribution override (defaults to you)"
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"room_id",
"body"
]
}arc_recall
Recall agent memory for a room, or for a whole project: direct memory hits first, then broader context hits from messages, decisions, artifacts, and skills, so you never replay whole transcripts. room_id defaults to your joined room; pass project_id instead to recall across every ACTIVE room in the project (hits carry room_id and room_name; the default room is named up front) — the right call when you know the project but not which room holds the memory.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | no | string | room to recall from; defaults to your joined room (or pass project_id) |
project_id | no | string | project to recall across: every active room, hits tagged by room |
query | yes | string | what the agent needs to remember |
namespace | no | string | optional memory namespace filter |
limit | no | integer | max memory/context hits per section; default 10 |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string",
"description": "room to recall from; defaults to your joined room (or pass project_id)"
},
"project_id": {
"type": "string",
"description": "project to recall across: every active room, hits tagged by room"
},
"query": {
"type": "string",
"description": "what the agent needs to remember"
},
"namespace": {
"type": "string",
"description": "optional memory namespace filter"
},
"limit": {
"type": "integer",
"description": "max memory/context hits per section; default 10"
}
},
"required": [
"query"
]
}arc_memory_status
Read a compact compact memory and room-state summary. With room_id (defaults to your joined room): namespaces, recent memory items, and a summary room status (decisions, tasks, artifacts, claims, what is yours) — the first call in a fresh memory-room session. With project_id: the project's default room, every active room with last_activity_at / artifact_count / is_default, and the memory namespaces + recent items across all of them (tagged by room) — the first call when you know the project but not the room. The room-status fetch defaults max_chars to 24000.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | no | string | room to summarize; defaults to your joined room (or pass project_id) |
project_id | no | string | project to summarize across its active rooms |
namespace | no | string | optional namespace filter for recent memory items |
limit | no | integer | max recent memories to return; default 5 |
max_chars | no | integer | room-status character budget; default 24000, floor 500 |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string",
"description": "room to summarize; defaults to your joined room (or pass project_id)"
},
"project_id": {
"type": "string",
"description": "project to summarize across its active rooms"
},
"namespace": {
"type": "string",
"description": "optional namespace filter for recent memory items"
},
"limit": {
"type": "integer",
"description": "max recent memories to return; default 5"
},
"max_chars": {
"type": "integer",
"description": "room-status character budget; default 24000, floor 500"
}
},
"required": []
}arc_create_handoff
Create a handoff: mints a fresh room with two role invites (ancestor + descendant) and attaches a packet (ancestor prose + daemon-snapshotted context from source_room_id). Returns room, both invites, and the packet.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
project_id | yes | string | See the schema below. |
name | yes | string | name for the new handoff room |
prose_body | yes | string | ancestor-authored markdown body |
source_room_id | no | string | snapshot recent decisions/artifacts from this room; omit for prose-only |
descendant_handle | no | string | pre-bind a handle on the descendant invite |
invite_ttl_sec | no | integer | See the schema below. |
by_agent_id | no | string | attribution override (defaults to you) |
topic | no | string | See the schema below. |
metadata | no | object | See the schema below. |
acl_override | no | object | broaden the descendant's scope: {readable_rooms: [room_ids it may read], writable_rooms: [room_ids it may post to]}, same project only; default readable=[source_room_id, handoff_room_id], writable=[handoff_room_id] |
request_id | no | string | idempotency key; retry a timed-out write with the SAME id (never duplicates) |
Complete input schema
{
"type": "object",
"properties": {
"project_id": {
"type": "string"
},
"name": {
"type": "string",
"description": "name for the new handoff room"
},
"prose_body": {
"type": "string",
"description": "ancestor-authored markdown body"
},
"source_room_id": {
"type": "string",
"description": "snapshot recent decisions/artifacts from this room; omit for prose-only"
},
"descendant_handle": {
"type": "string",
"description": "pre-bind a handle on the descendant invite"
},
"invite_ttl_sec": {
"type": "integer"
},
"by_agent_id": {
"type": "string",
"description": "attribution override (defaults to you)"
},
"topic": {
"type": "string"
},
"metadata": {
"type": "object"
},
"acl_override": {
"type": "object",
"description": "broaden the descendant's scope: {readable_rooms: [room_ids it may read], writable_rooms: [room_ids it may post to]}, same project only; default readable=[source_room_id, handoff_room_id], writable=[handoff_room_id]"
},
"request_id": {
"type": "string",
"description": "idempotency key; retry a timed-out write with the SAME id (never duplicates)"
}
},
"required": [
"project_id",
"name",
"prose_body"
]
}arc_get_handoff
Read the handoff packet for a room created by arc_create_handoff: prose_body plus the snapshotted decisions/artifacts/open tasks carried over from the source room. Use when joining a descendant room to recover the full handoff context.
| Argument | Required | Type | Description / schema default |
|---|---|---|---|
room_id | yes | string | the handoff room's id |
Complete input schema
{
"type": "object",
"properties": {
"room_id": {
"type": "string",
"description": "the handoff room's id"
}
},
"required": [
"room_id"
]
}