Server definition
- Hash
- sha256:61ad043dee3e6a469f195fed0c625f582ecf17f1298345801b20836780e03516
- What it is
- What a remote MCP server returned when asked what it offers: 19 tools
The blob, as servednamed by its sha256
{
"instructions": null,
"tools": [
{
"description": "Call this ONCE at the START of a session, before there is a task: it opens a rolling, expandable digest of what happened recently across every project this person belongs to, using each entry's authored essence, AND opens with the roster of their projects — every slug and what each one is for. Open handoffs are a separate block from completed work and are never displaced by the log. When the digest spans responses, continue with the read_id and receipt returned by the last part: they are the cursor over one frozen window. Use arroway_read include:[\"#handle\"] when the full body matters. This is the 'where do things stand' read; arroway_read is the task-specific one.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"days": {
"description": "How many days back, counting today. Default 2 — yesterday and today, which is what a session normally needs to know where things stand. Ask for more only when you are picking up work after being away.",
"maximum": 30,
"minimum": 1,
"type": "integer"
}
},
"required": [],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_catch_up",
"outputSchema": null
},
{
"description": "Mark that you are taking an open handoff, BEFORE working on it, so parallel sessions see it is taken and do not duplicate the work. A claim is a mark, never a lock: it stops nobody, a stale claim is information, and claiming again overwrites the mark while saying whose it was. Addressing rule: addressed to YOUR user — take it; addressed to someone else — only a human in this conversation can decide to take it anyway, and an autonomous session must leave it. When the work lands, close it with arroway_close.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"handoff": {
"description": "The #handle from the read (8 chars), or the full id.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"note": {
"description": "Who is taking it, in plain words — a routine names itself here (e.g. 'nightly build routine').",
"maxLength": 16384,
"minLength": 1,
"type": "string"
},
"project": {
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
}
},
"required": [
"project",
"handoff"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_claim",
"outputSchema": null
},
{
"description": "Close an open handoff when the work it carried is DONE — call it alongside the arroway_log entry that records the residue. Closing without a completion log leaves the team an ending with no story. Work that removes what an open handoff exists to fix closes that handoff in the same pass — even when the handoff is someone else's. So this is also the call for someone ELSE's handoff, when your work emptied it: the file it wanted fixed left circulation, the card it pointed at was cancelled, the decision behind it was reverted. Close it in that same pass, with a note naming what emptied it — an open handoff whose object is gone keeps billing a person for work that no longer exists. What is NOT this: a handoff that still carries real work, which a passer-by must never close. And if the work turned out not to be worth finishing, that is not yours to decide alone: discarding a handoff is the human's gesture, in the panel.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"handoff": {
"description": "The #handle from the read (8 chars), or the full id.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"note": {
"description": "One line on what landed — it points at the residue, it does not replace it.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
},
"project": {
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
}
},
"required": [
"project",
"handoff"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_close",
"outputSchema": null
},
{
"description": "After the final part of a multi-part Arroway read arrives, acknowledge it with its read_id and receipt. This closes the sequence and records that the whole snapshot was received. It is not a precondition for working: delivery is already recorded when the first part arrives.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"read_id": {
"description": "Opaque id returned by the incomplete arroway_read response.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"receipt": {
"description": "Opaque receipt returned by the final part.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
}
},
"required": [
"read_id",
"receipt"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_complete_read",
"outputSchema": null
},
{
"description": "Configure how a known external referrer is counted in Arroway's acquisition view. This is a product-wide operational setting, available only to a product administrator: use it when that administrator explicitly asks to map a domain to a source and channel. It stores only the domain and two short labels, never a visitor address or browsing history. Calling it again for the same domain replaces the mapping, so a new source can be recognised without a deploy.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"channel": {
"description": "Short channel label, such as organic-social, directory or referral.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"domain": {
"description": "External hostname only, such as linkedin.com — no URL, path or query string.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"source": {
"description": "Short source label, such as linkedin or anthropic-directory.",
"maxLength": 2048,
"minLength": 1,
"type": "string"
}
},
"required": [
"domain",
"source",
"channel"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_configure_referrer",
"outputSchema": null
},
{
"description": "Fetch more of an Arroway read that did not fit in one response. Send exactly the read_id and receipt from the preceding part; each call acknowledges that part and returns the next one. Continuing is OPTIONAL and deliberate: the first part carries the project's norms in full and already counts as a delivered read, and it lists by name what the later parts hold. Call this when something in that list bears on your task — not as a formality.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"read_id": {
"description": "Opaque id returned by the incomplete arroway_read response.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"receipt": {
"description": "Opaque receipt returned by the immediately preceding part.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
}
},
"required": [
"read_id",
"receipt"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_continue",
"outputSchema": null
},
{
"description": "Export what this project has DECIDED as a portable memory pack — a document you can hand to another team, keep as a file, or import into another project. Only sanctioned, live memories travel: a proposal is not a norm yet, an archived one stopped being one, and a FINDING never was one — findings are context nobody sanctioned, so they stay in the project and the answer tells you how many did. Nothing about people travels — no author, no who sanctioned it, no row identifier, and no memory about WHO SOMEONE IS. The pack is what the team decided, never who was there. Give it a name that says what it is for, because that name is what the person on the other side sees before deciding whether to trust any of it.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"description": {
"description": "Optional: who this pack is for and what it assumes. Written for someone who has never seen this project.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"name": {
"description": "What this pack IS, in a few words — the vertical, the practice, the playbook. It travels with the document and is the first thing the other side reads.",
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"project": {
"description": "Slug of the project whose norms you are exporting",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"topic": {
"description": "Optional: export only the memories carrying this topic. Use it to hand over one practice instead of everything a project knows.",
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"name"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_export",
"outputSchema": null
},
{
"description": "Bring a memory pack into a project. Everything in it lands as a PROPOSAL for the human to sanction in review — never as an active rule, no matter what the pack says about itself. A pack has the authority to ASK, never to decide: what arrives is a stranger's opinion until someone here says otherwise. Nothing is pinned on import either, because pinning spends this project's reading budget in every session from now on, and that is the owner's call with their own shelf in view. If any part of the document is malformed, NOTHING is imported and the refusal says how many units were left out — half an import is worse than none, because the memory that did not make it is the one nobody will go looking for.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"pack": {
"description": "The pack document itself, as it was written by arroway_export. Read the file and pass its contents — this server does not fetch URLs on your behalf.",
"type": "object"
},
"project": {
"description": "Project slug. If it did not come from the person or from a read in this session, it is a guess: check it against the roster that opens arroway_catch_up before writing, because material from one circle must never land in another.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
}
},
"required": [
"project",
"pack"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_import",
"outputSchema": null
},
{
"description": "Append the durable residue of a COMPLETED task to your daily log in Arroway: what someone arriving later would need in order not to redo it. You judge the length — say what carries, cut what does not. Dated state (numbers, statuses) belongs here; it ages out naturally. Team-visible. ALWAYS write the authored essence too: it is the one line the normal project read serves. An older, frozen catalog that truly has no essence field may still write the body; Arroway marks that entry as pending a reviewable essence proposal, never as if one had been authored. One thing that belongs here and nowhere else: if the person corrected you for insisting on something already decided, say so in the entry, so the memory that keeps being re-litigated can be flagged. AND CLOSE WHAT THIS WORK REALIZED: every memory in the read carries 'dies when: …'. If this task made that condition true — the idea was built, the intention was carried out, the dated status was replaced — name it in `fulfills` and Arroway retires it in the same act, with this entry as the reason; the human never has to archive the obvious by hand. Only decisions, facts and references can be fulfilled, and only ones this connection actually received in a read.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"backfilled": {
"description": "True when the entry describes something that happened BEFORE Arroway existed (history you are bringing in), not today's work.",
"type": "boolean"
},
"content": {
"description": "The full durable residue: what was decided, found or changed, and what it cost. It remains recoverable by handle.",
"maxLength": 65536,
"minLength": 1,
"type": "string"
},
"essence": {
"description": "One authored line with the operative result. This is what the normal project read serves; never copy the opening of the body.",
"maxLength": 280,
"minLength": 1,
"type": "string"
},
"fulfills": {
"description": "ARROW-290. The memories this completed work REALIZED — their 'dies when' condition is now true because of what you did (a routine that an idea asked for is running; a planned move was made; a dated status has been replaced by what this entry records). Each one is retired in the same act as this log, with your 'how' as the reason on its archived line, reversible from the panel. Guards: only decision/fact/reference (a rule is never 'fulfilled'), and only memories this connection received in full in a read — if any item fails, the whole call is refused and nothing is written. Never list a memory because it merely looks old or unused: that is not evidence.",
"items": {
"additionalProperties": false,
"properties": {
"how": {
"description": "What this work did that met the memory's kill condition — one sentence; it stays on the archived line forever.",
"maxLength": 1000,
"minLength": 1,
"type": "string"
},
"memory": {
"description": "The #handle from the read (8 chars), or the full id",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
}
},
"required": [
"memory",
"how"
],
"type": "object"
},
"maxItems": 20,
"minItems": 1,
"type": "array"
},
"keep_whole": {
"description": "Set true only after you considered cutting an indivisible oversized residue. Arroway records this exception for calibration; it never truncates your text automatically.",
"type": "boolean"
},
"operational": {
"description": "Set true when this is the record of HOW THE WORK WENT — what failed, what you measured, what you corrected about your own earlier reading. It is kept in full for catching up at the start of a session, and stays OUT of the task-scoped read, so a long account never pushes a teammate's residue out of their block. Leave it out (the default) for what the team needs to know HAPPENED: that is what reaches other people while they work. This is a record of work, never a transcript of the conversation.",
"type": "boolean"
},
"project": {
"description": "Project slug. If it did not come from the person or from a read in this session, it is a guess: check it against the roster that opens arroway_catch_up before writing, because material from one circle must never land in another.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"source": {
"description": "Optional pointer to a living source (URL, doc, CRM id)",
"maxLength": 2048,
"minLength": 1,
"type": "string"
},
"topic": {
"description": "Optional free tag (e.g. 'marketing')",
"maxLength": 120,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"content"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_log",
"outputSchema": null
},
{
"description": "PROPOSE that a memory belongs in a different project — you never move it yourself. Moving changes WHO SEES IT: leaving a team project removes it from the team, and going from a personal project to a shared one exposes it. So this only queues the change for the human's review. Use the #handle from the read.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"memory": {
"description": "#handle of the memory, from a read",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"project": {
"description": "Slug of the project the memory is in TODAY",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"target": {
"description": "Slug of the project you believe it belongs to",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"why": {
"description": "Why it belongs there and not here — the human decides on this sentence",
"maxLength": 16384,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"memory",
"target",
"why"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_move",
"outputSchema": null
},
{
"description": "Call this in the seconds BEFORE you tell the person something or propose a course of action, to see whether it contradicts a decision the team already made. It returns the standing norms — the project's pinned rules and decisions, plus this person's own standing rules — AND THEN A MAP: the titles and handles of everything else the project remembers, so you can see whether anything there touches what you are doing. Read that map: if a title looks relevant, ask for it by handle with arroway_read include:[\"#handle\"], which GUARANTEES those memories come back in full and first, where the ranking could otherwise have left them out — it does not make that read any cheaper than a read without it, so name a handle to be sure of getting something, never to pay less for it. It is meant to be called often: many times in one session, whenever you are about to commit to a claim. The map gives you names, never content, so this still does not answer 'how do I do this' — no recent context, no daily log, no ranked material. When you are starting work on a task, that is arroway_read, and this does not replace it. Because it is meant to be repeated, it ends by printing a session checkpoint: pass it back as `since` on your next call for this project and the standing norms are referenced instead of reprinted, so the repetition costs the map and what is in flight rather than the whole fixed block again.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"project": {
"description": "Project slug the claim is about.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"since": {
"description": "Optional: the session checkpoint printed at the end of a previous arroway_norms call for THIS project. Presenting it lets the standing norms be referenced instead of reprinted, which is what makes calling this tool many times in one session cheap. It is this tool's own checkpoint — the one arroway_read prints is not interchangeable with it, because the two surfaces render the same memories at different fidelity. Omit it — or present one this connection does not hold — and the norms are written out in full; the server decides, never your local state. If your context was compacted or this is a new conversation, omit it.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
}
},
"required": [
"project"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_norms",
"outputSchema": null
},
{
"description": "Call this when you STOP with the task unfinished — out of time, blocked, or told to stop. It leaves a HANDOFF: the in-flight state of open work, served at the top of every read of this project until someone takes it and closes it. It does not replace the log: a COMPLETED task still ends in arroway_log; this exists for the one you could not complete. ALWAYS write the authored essence too: it is the default in-flight state served in reads. An older, frozen catalog that truly has no essence field may still pass the full state; Arroway marks it as pending a reviewable essence proposal, never as if one had been authored. Deliberate only — never a dump of the session: write exactly what the next session needs to continue without redoing or re-deriving anything. A handoff never expires by clock: it dies in exactly three ways — closed with arroway_close, replaced by another pass naming it as superseded, or discarded by a person in the panel. Age is reported in the read as information; it never removes anything.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"addressed_to": {
"description": "Optional name of a person or routine this is meant for. A visible convention, never a lock: everyone still sees it, and the read says who may take it.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"card": {
"description": "Pointer to the living tracker for this work (card id, issue, PR), when one exists.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"do_not_redo": {
"description": "What is already done, verified or decided that the next session must NOT redo or re-litigate.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"essence": {
"description": "One authored line that states the operative in-flight state. This is the default read; the full handoff remains recoverable by handle.",
"maxLength": 280,
"minLength": 1,
"type": "string"
},
"next_step": {
"description": "The single concrete next step. Not a plan: the step.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"open_risk": {
"description": "The risk left open — what could bite whoever continues.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"project": {
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"read_handles": {
"description": "The reading list the next session needs: #handles of the memories, log entries and handoffs — of THIS project — that whoever continues must read in full. You know what you had to read to get here; naming it spares them rediscovering it. Order is kept as you write it. At most 10 unique references, and going over is refused rather than trimmed, because each one comes back in full body. Only what is genuinely required to continue: a handle merely cited in do_not_redo is history, not required reading, and is not picked up from the text — it counts only if you name it here.",
"items": {
"maxLength": 36,
"minLength": 8,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"maxItems": 10,
"type": "array",
"uniqueItems": true
},
"supersedes": {
"description": "#handle of the OPEN handoff this one replaces, from a read. Replacement is explicit by reference, never guessed from titles.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"where_stopped": {
"description": "Where the work stands right now — what is done and verified, what is half-done.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"where_stopped",
"next_step"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_pass",
"outputSchema": null
},
{
"description": "Read Arroway for a project BEFORE acting on any task related to it. It serves the authored essence of memories, dated-log entries and handoffs by default; name a #handle in include to recover that object's full body.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"handoff": {
"description": "Optional: the #handle of an OPEN handoff you are continuing. The read is then built from that handoff's reading list (the read_handles its author named): the standing rules in full, the handoff and every reference it names in full, and nothing ranked — much smaller than a normal read, and it counts as a delivered read. A handoff with no reading list falls back to the normal read, and says so. Cannot be combined with include; `since` is ignored. If a reference on the list is no longer available, the read is refused rather than served incomplete — read normally instead.",
"maxLength": 4096,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"include": {
"description": "#handles of memories, dated-log entries or handoffs whose full body you need. They are placed first and cannot be dropped by the budget — so other memories fall out instead: this chooses what you get, it does not get you more.",
"items": {
"maxLength": 36,
"minLength": 8,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"maxItems": 10,
"minItems": 1,
"type": "array",
"uniqueItems": true
},
"project": {
"description": "Project slug, e.g. 'seven50'",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"since": {
"description": "Optional: the session checkpoint printed at the end of a previous read of THIS project. Presenting it lets the standing rules be referenced instead of reprinted, freeing that space for the task. Omit it — or present one this connection does not hold — and they are written out in full; the server decides, never your local state. If your context was compacted or this is a new conversation, omit it.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"task_context": {
"description": "Optional: what you are about to do. It ranks what comes back, but the declaration alone is NOT evidence that a memory was used. A matching completion residue from the same session must corroborate it before Arroway updates the memory's observed-use signal.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
}
},
"required": [
"project"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_read",
"outputSchema": null
},
{
"description": "Save a durable memory (decision/rule/fact/preference/reference/identity) as governed by default. For a source-backed fact or reference that is useful only as agent context, set treatment='finding' and explain why: it costs nobody a review, and is stored as CONTEXT, never a human-sanctioned norm, cannot be pinned, and is shown separately in Findings. A finding cannot replace a sanctioned memory; correcting another finding is in-place replacement with no human queue. A finding a person revoked cannot be written again unless they reconsidered in this conversation — related_checked does not unlock that. 'identity' is WHO someone is — a person, a relation, a background: it never expires, never pins by default, and comes back when the person is part of the task; someone from the user's own circle belongs in their personal project, people of a business in that business's project. If the human explicitly stated or sanctioned it in this conversation, set decided_by_human=true (memory becomes active). Otherwise it is saved as a PROPOSAL for the human's weekly review — never present a proposal as a decision. kill_condition is mandatory: what would kill or force a review of this memory. A RULE takes TWO calls: send it with no pin fields and no related_checked, read the neighbours and the block cost the server returns, then call again with the token it gave you and the pin decided against what you just saw. Any OTHER type stays one call unless you ask to pin it: sending pin_suggested or pin_requested_by_human starts the same comparison, and only the second call with the returned token can pin it. Any type that the server stops for strong related memories also takes TWO calls: read those memories, then return related_checked=true together with its related_check_token. A flag alone never proves a comparison happened.",
"inputSchema": {
"additionalProperties": false,
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "fact"
}
},
"required": [
"type"
]
},
"then": {
"required": [
"review_at"
]
}
},
{
"if": {
"properties": {
"expires": {
"const": true
}
},
"required": [
"expires"
]
},
"then": {
"required": [
"review_at"
]
}
}
],
"properties": {
"backfilled": {
"description": "True when this is HISTORY you are bringing in — something that was already true before Arroway existed, not something that just happened. The moment to use it: you finished a task about topic X, the read came back thin on X, and the work took you to a durable SOURCE about X — a file in this workspace, a document, a ticket. Then write that history too. Only the topic you just worked on, never a project dump; only what you can point a source at, never your own recollection of past conversations; a few memories, not a batch.",
"type": "boolean"
},
"content": {
"description": "The norm ITSELF, written as if it were true today and nobody had to be told how it got here. Length is never free: this body is re-read by every assistant on this project, on every read, from now on — write the shortest version that still governs correctly. Keep only the reasoning WITHOUT WHICH the rule would be applied wrongly; if removing a sentence would not change anyone's next action, it is biography, not norm. Leave out the biography: who said it, on what date, their exact words, the episode that produced it, and numbers measured on a particular day — all of that goes in why_source. A body that opens with a quote makes the next assistant follow the quote instead of the rule, and a date in the body makes it discount the whole memory as possibly stale. If a GENERAL rule shows up while you are writing about a specific case, the general rule is the memory and the case is the example — not the other way round: the case goes in the example field, never here. Condense: a memory per sentence is how Arroway fills with near-duplicates.",
"maxLength": 65536,
"minLength": 1,
"type": "string"
},
"contradiction": {
"description": "Required with supersedes_id: name what the earlier memory says that this one contradicts or changes. This is the named contrast that proves it is the same point, not merely a neighbour on the same topic. Do not point at a memory that can be followed alongside this one.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"decided_by_human": {
"description": "true ONLY when the person stated or sanctioned this in THIS conversation. Never because it looks obviously right to you. false makes it a PROPOSAL for their review, which is the normal case — and a proposal is never free: it costs that person a review, whether they end up approving it, editing it or turning it down. What it costs afterwards depends on where it sits: only a PINNED memory travels in every read of the project from now on; a normal memory competes for space in the block relevant to the task at hand. So the question that decides whether to write at all is not what the write costs you — it is whether this would change what someone does on a DIFFERENT task. Three things never pass that question, however true they are: an instruction to check, verify, be careful or look at the source; a step of a routine, which belongs in the prompt that runs it; and anything that is here only because something went wrong once.",
"type": "boolean"
},
"essence": {
"description": "The memory's essence in ONE line: the operative norm or fact, not the first sentence and not its biography. This is the compressed layer that always travels when the full body does not fit.",
"maxLength": 280,
"minLength": 1,
"type": "string"
},
"example": {
"description": "A concrete case that ILLUSTRATES the rule — the human sees it in the panel next to the rule; it NEVER travels in reads, so no assistant can mistake the case for the rule's scope. If the rule cannot be applied correctly without this example, the example is smuggling a criterion: name that criterion in content instead. Quotes, dates and the episode that produced the rule still belong in why_source.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
},
"example_considered": {
"description": "Only after the server flagged the body as carrying its example: set true to confirm you re-read it and what looks like an example there is actually criterion the rule needs — an exact string it matches on, a deadline it carries. Never set it blindly on a first call.",
"type": "boolean"
},
"expires": {
"description": "ARROW-78. Set true ONLY for a dated STATUS — a number, a rollout state, a temporary condition — where being read after review_at would assert something stale as current: it stops being returned once the date passes. Leave it out for a durable fact that merely needs re-checking (a market structure, how a tool works): that one keeps being returned, marked as due for re-check. If unsure, leave it out — a fact that vanishes leaves no trace, one that comes back marked cannot be mistaken for current.",
"type": "boolean"
},
"kill_condition": {
"description": "Mandatory: explicit revocation / named trigger / review date",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"pin_decision_token": {
"description": "The token the server gave you on the first call for a pin decision. A rule always uses this two-call flow; every other type uses it whenever pin_suggested or pin_requested_by_human is present. The first call returns the neighbouring memories with the pin state of each and what the fixed block currently costs, and only the second one writes. Send the token back unchanged on that second call, together with the pin decision. It is tied to the exact title and body you compared, works once, and expires — a comparison you cannot prove is a comparison that did not happen, so a confirmation without it is refused and nothing is written.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"pin_requested_by_human": {
"description": "true ONLY when the person, in THIS conversation, told you to fix this memory in every session — 'pin this', 'this has to be in every session', 'always send this'. On any type, sending it begins the two-call comparison; only the return with pin_decision_token records the order. Sanctioning the CONTENT is not asking for the pin: they can agree a memory is right, and correct, and still never have asked for it to travel in every read. Those are two different facts and the server records them separately. Their order pins immediately, above any ceiling, and the block's hygiene is then theirs; your own judgement goes in pin_suggested and passes through the ceiling. Never set this because the pin looks obviously right to you — that is pin_suggested.",
"type": "boolean"
},
"pin_suggested": {
"description": "Whether this memory sits in the fixed block of EVERY read, costing tokens in every session of this project from now on. There is no default: a rule requires this on its confirming call, and any other type carrying this field begins the same two-call comparison. The first call does not decide the pin; return this value only with pin_decision_token after the server showed the neighbours and cost. Three questions decide: does breaking this cause expensive or irreversible damage · does it apply to every task, or only when someone touches one area · would the next person have found it anyway when they opened the relevant file? A memory discoverable where it matters is a reference or a fact, not a pinned rule. What a pin actually costs: it does not displace another pin — it eats the SAMPLED space of every read, which is where the memories relevant to someone else's task come from. This field carries YOUR judgement, so above the block's ceiling the server turns it into a proposal of the pin alone and the memory itself still lands. The person's own order is pin_requested_by_human, and it is not this field.",
"type": "boolean"
},
"project": {
"description": "Project slug. If it did not come from the person or from a read in this session, it is a guess: check it against the roster that opens arroway_catch_up before writing, because material from one circle must never land in another.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"related_check_token": {
"description": "The one-use token the server returned with related memories. It proves this confirmation follows THAT comparison and is tied to this exact text.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"related_checked": {
"description": "Only after the server showed you related memories: set true with related_check_token to confirm you read them and this is a genuinely different point, not an update to one of them. Never set either blindly on a first call.",
"type": "boolean"
},
"review_at": {
"description": "ISO date (YYYY-MM-DD) when this stops being true on its own — the end of a cycle, a deadline, a season. This is how a COMMITMENT is carried: an objective is a decision with a horizon. REQUIRED for type=fact, and there it also removes the memory from reads once the date passes. Leave it empty only for something with no expiry date at all.",
"format": "date",
"maxLength": 10,
"minLength": 1,
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"revoked_reconsideration": {
"description": "Required when a related finding was revoked by a person: quote what they said in THIS conversation that reconsiders it. related_checked does not unlock rewriting a revoked finding. Do not promise that old prompts or past actions will be undone.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"source_ptr": {
"description": "Pointer to the living source, when verifiable",
"maxLength": 2048,
"minLength": 1,
"type": "string"
},
"split_considered": {
"description": "Set true only after you looked for the seams and this genuinely has to stay whole. Splitting is the default: a long memory usually holds a norm, the reasoning behind it, and a checklist — and only the first belongs here.",
"type": "boolean"
},
"supersedes_id": {
"description": "If this replaces an earlier memory: its #handle from a read. Point only when the two memories are the SAME point: acting on either would already satisfy or violate the other. A shared topic is not enough — if both can be followed together, they are different memories.",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"title": {
"description": "Short, unique within the project",
"maxLength": 200,
"minLength": 1,
"type": "string"
},
"topic": {
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"treatment": {
"description": "Which of two destinations this write takes, and they cost different people. `governed` enters the person's review queue, and that review is a real cost to them — pay it for what governs. `finding` costs nobody a review: it is served to agents as context, never becomes a sanctioned norm, cannot be pinned and cannot replace one. The line between them is not the topic, it is the force: does this GOVERN what someone may or must do, or only INFORM? Governs → governed. Informs, and points at a source another agent can reopen and compare — a file, a URL, a record, a query → finding, and only fact and reference qualify.",
"enum": [
"governed",
"finding"
],
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"treatment_justification": {
"description": "Required with treatment=finding: say why this is verifiable context rather than a policy, priority, procedure, or decision for a person.",
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"type": {
"enum": [
"rule",
"decision",
"fact",
"preference",
"identity",
"reference"
],
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"why_source": {
"description": "Where it came from, and this is the ONLY place biography belongs: who decided, when, in their words, what was measured, which episode produced it. This does NOT travel in reads — it is what a person sees when auditing the memory in the panel, and what tells them whether the rule still deserves to exist. Writing it here costs nothing to whoever reads Arroway while working; writing it in the body costs every assistant, every read.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"type",
"title",
"content",
"essence",
"decided_by_human",
"kill_condition"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_remember",
"outputSchema": null
},
{
"description": "Retire a memory the human already sanctioned, when THEY told you in this conversation to remove it and there is nothing to put in its place. It is archived, never deleted: it leaves reads and stays in the history with their reason, or with an explicit note that no reason was declared. Use arroway_remember with supersedes_id instead when you have a corrected version — that is replacement, not retirement. Use arroway_withdraw instead for a proposal YOU wrote that is still pending.",
"inputSchema": {
"additionalProperties": false,
"allOf": [
{
"properties": {
"decided_by_human": {
"const": true
}
}
}
],
"properties": {
"decided_by_human": {
"description": "Must be true, and only when the person explicitly told you to remove it IN THIS CONVERSATION. Never infer it, never set it because it looks obsolete to you: a sanctioned memory is theirs. Without their word, say it is a gesture for them to make in the panel.",
"type": "boolean"
},
"memory": {
"description": "The memory to retire — the #handle from a read is enough.",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"project": {
"description": "Project slug.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"why": {
"description": "Optional: what the person said made it obsolete, in their terms. It stays on the archived line forever; if omitted, the history explicitly says no reason was declared.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"memory",
"decided_by_human"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_retire",
"outputSchema": null
},
{
"description": "Search the recent DATED LOG for a literal term or phrase when you need to know WHERE something was said. It matches the authored one-line essence as well as the body, so a fixed term written as the entry's state line is found. By default it scans every project this person belongs to; pass project to narrow it. Returns compact excerpts anchored by project, date and entry — never full days, and each excerpt says when it came from the essence. This searches what happened, not curated memory, and does NOT replace arroway_read before acting on a task.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"project": {
"description": "Optional project slug. Omit it to search every project this person can access.",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"query": {
"description": "Literal term or phrase to find in recent dated-log entries. Matching is case-insensitive.",
"maxLength": 200,
"minLength": 1,
"type": "string"
}
},
"required": [
"query"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_search_log",
"outputSchema": null
},
{
"description": "Open a NEW project in Arroway, when the work at hand has no home. Use it when a read refuses an unknown project, or when you notice you have been working on something for a while with nowhere to write it. Propose the name and scope to the human in the conversation FIRST and only call this once they agree — then say it exists and can be renamed or killed in the panel. Scope is mandatory: it is the sentence that stops one circle's material from being written into another.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"name": {
"description": "How people will call it",
"maxLength": 120,
"minLength": 1,
"type": "string"
},
"scope": {
"description": "What belongs here and what does not. Written for the next assistant to read before writing — say the subject AND name what is out.",
"maxLength": 8192,
"minLength": 1,
"type": "string"
},
"slug": {
"description": "Short, lowercase, hyphenated, unique — e.g. 'trading-solana'",
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
}
},
"required": [
"slug",
"name",
"scope"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_start_project",
"outputSchema": null
},
{
"description": "Record what you found when your work ALREADY took you to a memory's source. This is bookkeeping, not an errand: never go verifying memories as a task — measured over a month, that never happens. But when you open a file, query, ticket or CRM that a memory points at, and you can see whether it still holds, say so here. Use the #handle shown in the read. Never guess an outcome you did not actually see. What the evidence decides, Arroway closes by itself (ARROW-290): a FACT whose source is proven gone is retired on the spot; a FACT whose source says something different is retired the moment you propose the correction with arroway_remember supersedes_id in this same session. On a FINDING, source_gone archives it the same way; conflicts is corrected in place with treatment=finding and supersedes_id, with no human queue. Rules and decisions are never retired this way — they only get marked.",
"inputSchema": {
"additionalProperties": false,
"allOf": [
{
"if": {
"properties": {
"outcome": {
"const": "conflicts"
}
},
"required": [
"outcome"
]
},
"then": {
"required": [
"note"
]
}
},
{
"if": {
"properties": {
"outcome": {
"const": "source_gone"
}
},
"required": [
"outcome"
]
},
"then": {
"required": [
"note"
]
}
}
],
"properties": {
"memory": {
"description": "The #handle from the read (8 chars), or the full id",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"note": {
"description": "Required for 'conflicts' (what the source actually says — it is what lets a human fix it without checking again) and for 'source_gone' (what you saw that proves removal — a note describing a timeout, an auth failure or a service being down is refused).",
"maxLength": 16384,
"minLength": 1,
"type": "string"
},
"outcome": {
"description": "matches = the source says what the memory says · source_gone = the source is PROVEN REMOVED (404, file deleted from the repository, record gone) — never 'unreachable': a timeout, a login wall or a service that is down is unavailability, and nothing is retired for it · conflicts = the source says something DIFFERENT (then also call arroway_remember with supersedes_id; on a fact that proposal retires the wrong fact at once; on a finding the correction replaces it in place, with no human queue)",
"enum": [
"matches",
"source_gone",
"conflicts"
],
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
"project": {
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
}
},
"required": [
"project",
"memory",
"outcome"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_verify",
"outputSchema": null
},
{
"description": "Take back a pending PROPOSAL that turned out to be wrong — typically because the human corrected you after it was written. Pending proposals only; a memory the human already sanctioned is theirs, and changing it goes through them. A proposal written by SOMEONE ELSE's AI can also be taken back — the archive belongs to the project — but Arroway stops first, names who wrote it and what would leave their review queue, and the next call with other_author_confirmed=true finishes it. This is not deletion: the proposal is kept, marked as withdrawn, with your reason. If the corrected version is durable, write it with arroway_remember too — leaving the right answer only in your own notes is how Arroway ends up holding the wrong one.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"memory": {
"description": "#handle of the proposal, from a read",
"maxLength": 36,
"minLength": 1,
"pattern": "^#?(?:[0-9a-fA-F]{8,32}|[0-9a-fA-F]{8}-[0-9a-fA-F-]{27})$",
"type": "string"
},
"other_author_confirmed": {
"description": "Only after Arroway told you the proposal was written by someone else's AI: set true to go ahead. Never set it blindly on a first call — the point of the stop is that the person hears whose work is leaving the queue before it leaves.",
"type": "boolean"
},
"project": {
"maxLength": 63,
"minLength": 1,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"type": "string"
},
"why": {
"description": "What made it wrong — usually what the human said. This is the part worth keeping.",
"maxLength": 16384,
"minLength": 1,
"type": "string"
}
},
"required": [
"project",
"memory",
"why"
],
"type": "object",
"x-maxSerializedLength": 131072
},
"name": "arroway_withdraw",
"outputSchema": null
}
]
}Verify it yourself
curl -s https://api.teppi.xyz/v1/evidence/sha256:61ad043dee3e6a469f195fed0c625f582ecf17f1298345801b20836780e03516 | sha256sum