{ "about": "How one prompt runs: model step, tool calls, results, again — and what ends it early. Both harnesses run this loop; the numbers are each project's defaults, the behaviour is the spec's.", "steps": { "about": "A runaway backstop, not a working budget: a prompt is meant to run until the task is done, and a step count low enough to end it ends it halfway. Past it the tools are withdrawn and the model answers (wrap_up).", "default": 200 }, "budgets": { "about": "What one prompt may spend. Checked between steps, never mid-reply — a reply cut off mid-sentence is worth nothing. Time spent waiting for the user (an approval, a question, a plan) is not counted. Past one, the tools are withdrawn and the model answers from what it has (wrap_up). The CLI leaves them unset by default (one user at their own terminal); LLeMbas sets them, and a group's quota can narrow them.", "wall_seconds": { "about": "Seconds of work.", "cli": null, "llembas": 900 }, "output_bytes": { "about": "Bytes of tool output read: a model filling its own context with build logs has no room left to answer.", "cli": null, "llembas": 1048576 }, "completion_tokens": { "about": "Tokens the model writes.", "cli": null, "llembas": 200000 } }, "wrap_up": { "about": "One more request, with the session's tool list unchanged (context.md §10, rule 4) and a user message saying which limit was reached: answer now — what is done, what is not, what would come next. The transcript says the prompt was stopped, so an answer given because the room ran out is never mistaken for one the model chose to give. A tool call in that reply is not run.", "message": "The {{limit}} for this prompt has been reached and the tools have been withdrawn. Answer now from what you have: what is done, what is not, and what would come next." }, "nudges": { "about": "A reply with only thinking, or one cut off at the output limit, is asked again (at most twice in a row) instead of ending the prompt with nothing said.", "max": 2 }, "parallel": { "about": "Calls in one step run together, at most 4; a call that waits on the user (ask_user, plan_submit) runs alone; two calls on one file run in order. A tool's error is its result, never the end of the prompt.", "max": 4 }, "capacity": "A subagent (task) is not started on a model whose server cannot hold it beside the prompt's own model — or beside the model of a subagent already running: another model of a connection that holds one model at a time, or the same model when it already serves as many of this session's requests as it can at once (models/schema.json capacity: `parallel`, `single_session` being parallel 1). A team's members are not refused there: they wait for a slot (team.md, Capacity).", "jobs": { "about": "Background work owned by a session: a command (bash `background: true`, or one still running when its timeout passed) or a subagent (task `background: true`). One id sequence per session (job1, job2, …), one list (job_list), one way to read (job_output), to stop (job_stop) and, for a subagent, to message (job_send); a subagent's own tools see only the jobs it started. A job that ends wakes the session that owns it: while a prompt runs, as a user message at the next step boundary; otherwise as a new turn of its own, marked `machine` so a UI shows it as the harness's, not the person's. A session that is not open keeps the note until it is resumed. Every such message begins with its mark, said rather than hidden: a model refuses an unmarked one as an injection (conformance/jobs.json gives the texts).", "marks": { "command": "[A background job you started has finished:]", "subagent": "[A subagent you started has finished:]", "message": "[A message from a subagent you started:]", "to_subagent": "[The main agent sent this while you were working — take it into account from here:]" }, "note_tail_chars": { "about": "Of a finished command's unread output, how much the note carries (the end of it).", "default": 4000 }, "finished_kept": { "about": "Finished jobs kept per session, oldest forgotten first.", "default": 50 }, "running_max": { "about": "Background commands one session may have running at once; past it, bash refuses to start another.", "default": 8 }, "subagent_steps": { "about": "The step backstop of a subagent (the CLI: limits.subagent_steps).", "default": 50 }, "lifecycle": "A subagent's own background commands stop when it ends, and its report says so. A session's jobs stop when the session is deleted. A front end asked to exit while jobs run asks the person first; one with nobody to ask waits for the jobs the prompt started, then stops the rest." }, "team": { "about": "Teams (spec 3.2.0, team.md): a lead and the members it adds, who talk in the team's room. The texts are said word for word; {{size}} is the team's size after the call (team.md §3), {{names}} names joined with \", \" in tree order. conformance/team.json.", "agents": { "about": "The chat setting agents {min, max}: the agents a team may have, the lead included. 1 ≤ min ≤ max ≤ cap. min and max are a new chat's defaults; cap is the instance's (LLeMbas) or the global configuration's (the CLI).", "min": 1, "max": 4, "cap": 32 }, "names": { "about": "A member's name: unique in the team; `lead` is the lead's, `all` addresses everyone.", "pattern": "^[a-z][a-z0-9-]{0,31}$", "lead": "lead", "reserved": [ "all", "lead" ] }, "marks": { "message": "[Team message from {{from}} to {{to}}:]", "report": "[Team report from {{from}} to {{to}}:]" }, "unavailable": { "about": "What a team tool answers while its requirement `team` is not met (team.md §2). one_agent is also each team tool's own `unavailable`, and what task answers while a team is offered, max is 1 and the lead has no member.", "one_agent": "The person allows one agent in this chat: there is no team. Do the work yourself.", "one_request": "This model serves one request at a time now, so there is no team. Do the work yourself." }, "work": { "about": "What a manager may not do itself (team.md §6): every call whose risk class is write or execute — an MCP tool's is read when it says readOnlyHint, else execute — but `job_stop`, and a `bash` call that the default rules alone allow in manual mode (reading commands). The tool list is unchanged; these answer texts.manager.", "write": [ "apply_patch", "edit", "mkdir", "multiedit", "mv", "rm", "skill_manage", "write" ], "execute": [ "bash", "branch", "commit", "merge", "pr", "python", "release", "tag" ], "kept": [ "job_stop" ] }, "read_max": 50, "texts": { "added": "Added {{name}} ({{role}}): it is working. Its report comes to you when it finishes. The team is {{size}} of {{max}} agents.", "added_waiting": "Added {{name}} ({{role}}): it waits for a free slot — the model serves {{parallel}} requests at once and all are busy — and starts when one frees. Its report comes to you when it finishes. The team is {{size}} of {{max}} agents.", "sent": "Sent to {{to}}.", "stopped": "Stopped {{names}}. The team is {{size}} of {{max}} agents.", "manager": "You lead a team: give this to a member (team_add or team_send).", "full": "The team is full: it has as many agents as the person allows ({{max}}). Give the work to a member already on it (team_send), or stop one (team_stop) first.", "bad_name": "{{name}} cannot be a name: use lowercase letters, digits and hyphens, beginning with a letter, at most 32 characters.", "all_name": "all addresses the whole team; it cannot be a name.", "taken": "There is already an agent called {{name}} in this team. Choose another name.", "no_goal": "Say the team's goal in `goal`, in one line, with your first member: every member is told it.", "unknown": "No agent called {{name}} in this team. The team: {{names}}.", "self": "That is you: send it to someone else.", "nobody": "Nobody else is on the team yet: add a member with team_add.", "not_yours": "{{name}} is not under you: you can stop only the members you lead, directly or through your members.", "nobody_to_stop": "No member is under you: there is nobody to stop.", "no_report": "(no report)", "ended": "[ended: {{reason}}]" }, "read": { "about": "team_read's answer: the tree, then the room. Agents in tree order (an agent, then its members in the order they were added, depth first), indented two spaces per level below the lead. `last`: `active now` while working, else how long ago its last turn ended (durations as jobs write them: \"5s ago\", \"1m 05s ago\"). A message's text: its first line after the colon, every further line indented two spaces. Messages above `since` the caller may see, oldest first, at most read_max; `more` when there are others after the last shown.", "tree": "Team ({{size}} of {{max}} agents):", "agent": "{{indent}}- {{name}} — {{role}} · {{state}} · {{model}} · {{last}}", "lead_role": "leads the team", "states": { "working": "working", "waiting": "waiting for a slot", "finished": "finished", "idle": "idle" }, "active": "active now", "room": "Room since #{{since}}:", "message": "#{{n}} {{from}} → {{to}}: {{text}}", "report": "#{{n}} {{from}} → {{to}} (report): {{text}}", "none": "No messages since #{{since}}.", "more": "More after #{{last}}: team_read with since {{last}}." } }, "context": { "about": "Context hygiene (spec 3.0.0, the prefix from 3.1.0; context.md): every measure acts when a result is inserted, and nothing already sent to the model is ever rewritten — changing earlier context throws away the prompt cache from that point. conformance/context.json gives the texts.", "ids": { "about": "Every tool result gets an id: `#` and its number in the session, counting from 1, in lowercase hex, at least 4 digits (`#0001`, `#000a`, `#10000`) — unique in the session and never reused (not after a compaction either), so `recall` finds any of them. It is the first thing in the result, in brackets.", "digits": 4 }, "read_header": "[{{id}} {{path}} lines {{from}}-{{to}} of {{of}} sha {{sha}}]", "read_header_empty": "[{{id}} {{path}} empty sha {{sha}}]", "edit_header": "[{{id}} {{path}} sha {{sha}}]", "header": "[{{id}}]", "unchanged": "Unchanged since {{earlier}}, which already shows lines {{from}}-{{to}}.", "same_result": "Same result as {{earlier}}.", "elided": "[{{n}} lines elided, full output {{id}}]", "created": "Created, {{n}} lines.", "no_result": "No stored result {{target}} in this session.", "recall_header": "[{{id}} recall {{target}} lines {{from}}-{{to}} of {{of}}]", "sha_digits": 8, "cap": { "about": "A result over max_lines lines or max_chars characters keeps its head (as many whole lines as fit both head limits) and its tail (likewise, from what is left), with the elided line between. When even the first line does not fit head_chars, it is cut to it and ends ` […cut]`, and the elided line follows however many whole lines it counts (0 included): it is there whenever anything was left out. Not applied to read (its own window: 2000 lines from an offset) or recall (likewise). The full output is stored with the session.", "max_lines": 400, "max_chars": 40000, "head_lines": 200, "head_chars": 20000, "tail_lines": 100, "tail_chars": 10000 }, "dedupe": { "about": "by_hash: a read whose file (by its absolute path) has the same content hash as an earlier full read in the table, and whose lines lie wholly inside that read's, is answered with `unchanged`. by_result: a call with the same arguments as an earlier one in the table, whose result is the same text, is answered with `same_result`. Stubs point at the full result, never at another stub. The table is the full results in the request being built — never one the request does not carry (a chat's earlier reply, a turn undone) — and compaction empties it.", "by_hash": [ "read" ], "by_result": [ "list", "glob", "grep", "search" ] }, "compaction": { "about": "The one deliberate break of the cache. After the summary the harness adds the table of the reads the summary covers — the full reads made since the previous compaction, in turns still in the history being summarised, whether or not the request still carries them; of those the newest full read of each file, newest last, at most `rows` — and then empties the dedupe table, so no stub ever points at content that is gone from the context. No reads: no table.", "heading": "## Files read before this summary", "line": "Read a file again for its content; recall shows a result by its id.", "rows": 50 }, "reasoning": "Spec 3.2.0 (context.md §8): every assistant message of the current turn — the messages after the last one that started a turn (the person's, or a machine message that starts a turn of its own; a delivery at a step boundary does not) — carries the reasoning it came with (OpenAI chat: `reasoning_content`; Anthropic: its thinking blocks, unchanged); assistant messages of earlier turns carry none. What is stored keeps it. conformance/reasoning.json.", "env": { "about": "Spec 3.2.0 (context.md §11): the environment block's lines about where the session works, in an agent session. `project` always, `name` being the project root's last path component; `started` only when the session started in a directory below the root, `path` being that directory relative to the root. No absolute path. conformance/paths.json.", "project": "Project: {{name}} (paths are relative to its root)", "started": "Started in: {{path}} (relative to the project root)" }, "note": { "about": "A note on the next user message (context.md §10, rule 3): what changed since the system prompt was made, after the person's words. Lines in this order, each only when it applies. `plan_ended` is the mode block for a session that leaves plan mode for a mode with no text of its own (a chat). `plan_own` is the plan block for a session that does not resend earlier tool results (a chat): the model's own plan, as its tools left it. `personal` is the {{path}} of the instructions block for the person's own instructions. Spec 3.2.0, where a team is offered (team.md §10): `team` — the size setting, on the first user message and after it changes, followed in the same block by `team_lead` when min ≥ 2 ({{members}} = min − 1), or `team_one` in its place when max is 1; `team_stopped` — members the person stopped, a block of its own.", "open": "", "close": "", "date": "Today is {{date}}.", "mode": "The permission mode is now {{mode}}:\n{{mode_text}}", "plan_ended": "Plan mode has ended: make the changes the work needs; nothing is refused for planning any more.", "plan": "The person changed the plan; it is now:\n{{plan}}", "plan_own": "Your plan, as your plan tools left it:\n{{plan}}", "memory": "The person changed what is remembered; it is now:\n{{memory}}", "instructions": "{{path}} changed; it now reads:\n{{text}}", "personal": "the person's own instructions", "personality": "The person chose a different personality:\n{{personality}}", "mcp": "Instructions from an MCP server that connected since the session began:\n{{instructions}}", "team": "The team may have {{min}} to {{max}} agents, you included.", "team_lead": "Work through a team from the start: you lead, and members do the work — at least {{members}} of them.", "team_one": "The person allows one agent: work alone; the team tools and task are unavailable.", "team_stopped": "The person stopped {{names}}; they have left the team.", "empty": "(none)" }, "mcp_wait_ms": 3000 } }