Harness spec 3.4.0: progress phases, and subagents v2 — the main agent and its tree
ci / check (push) Waiting to run
ci / check (push) Waiting to run
progress.md: thirteen fixed phases (queued … failed), each { phase, since, data },
their texts as shared i18n keys (loop.json progress), one line every client draws,
sent beside the old status text in /api/v2 and over the link (capability progress).
subagents.md §5–§13 (supersedes team.md where they differ): only the main agent
adds, assigns, replaces, stops and decides; sub-managers direct those placed under
them; ids, positions, parents; Min above 1 opens slots; permissions inherited and
never widened, request options decided by the main agent, what nobody in the tree
can allow goes to the person; team_finish, findings, running out of context;
transcripts read-only; the tree over the link (capability tree). New tools
team_whoami, team_finish, team_findings, team_request, team_decide, team_assign,
team_replace. Conformance: progress, delegation; team updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
26 files changed
+1844
-97
No files matched your search
@@ -0,0 +1,431 @@
|
||||
{
|
||||
"about": "Delegation (subagents.md §7, spec 3.4.0): a subagent's mode and request options, and who decides its calls. The project root is /project, nothing named exists on disk, and only the default rules apply (permission/defaults.json). `add` — team_add's mode check for a parent in `parent_mode` with `mode` and `request` as given → `{result, mode}`: the refusal word for word, or null and the mode the subagent gets. `call` — a subagent in `mode` with `request` options and `grants` (rules {tool, pattern} the main agent allowed) under a main agent in `main_mode`, calling `call` (`bash` with a `line`, or a file tool with a `path` relative to the root) → `{answer, text?}`: `run`, `person` (an approval card to the person), or `refused` with its text where the case gives one (a hardline's reason is each project's). `unattended`: nobody can answer. `request` — team_request for `tool` by a subagent with `request` options, its first → `{result}`. `switch` — the main agent's mode changes from `main_from` to `main_to` with these subagents (each with its parent and mode) → each one's mode after. LLeMbas: services/team.py; CLI: team/delegation.ts.",
|
||||
"cases": [
|
||||
{
|
||||
"about": "No mode given: the parent's.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"expect": {
|
||||
"result": null,
|
||||
"mode": "edit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Stricter is allowed.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"mode": "manual",
|
||||
"expect": {
|
||||
"result": null,
|
||||
"mode": "manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Looser is refused, naming the parent's mode.",
|
||||
"op": "add",
|
||||
"parent_mode": "manual",
|
||||
"mode": "edit",
|
||||
"expect": {
|
||||
"result": "A subagent's mode cannot be looser than its parent's (manual).",
|
||||
"mode": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Plan is the strictest: anything else under it is looser.",
|
||||
"op": "add",
|
||||
"parent_mode": "plan",
|
||||
"mode": "auto",
|
||||
"expect": {
|
||||
"result": "A subagent's mode cannot be looser than its parent's (plan).",
|
||||
"mode": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Request options with the parent's own mode: nothing to ask for.",
|
||||
"op": "add",
|
||||
"parent_mode": "auto",
|
||||
"mode": "auto",
|
||||
"request": [
|
||||
"write"
|
||||
],
|
||||
"expect": {
|
||||
"result": "Request options go with a mode stricter than the parent's: without one there is nothing to ask for.",
|
||||
"mode": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Request options with no mode given (the parent's): refused the same way.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"expect": {
|
||||
"result": "Request options go with a mode stricter than the parent's: without one there is nothing to ask for.",
|
||||
"mode": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Request options with a stricter mode.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"mode": "manual",
|
||||
"request": [
|
||||
"write",
|
||||
"execute"
|
||||
],
|
||||
"expect": {
|
||||
"result": null,
|
||||
"mode": "manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "An unknown kind is refused, naming it.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"mode": "manual",
|
||||
"request": [
|
||||
"delete"
|
||||
],
|
||||
"expect": {
|
||||
"result": "delete is not a request option: use read, write or execute.",
|
||||
"mode": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "An empty list of request options is no options, and needs nothing.",
|
||||
"op": "add",
|
||||
"parent_mode": "edit",
|
||||
"request": [],
|
||||
"expect": {
|
||||
"result": null,
|
||||
"mode": "edit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "All in edit: an edit inside the project runs.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "edit",
|
||||
"call": {
|
||||
"tool": "edit",
|
||||
"path": "src/a.ts"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "run"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "All in edit: bash that edit mode asks goes to the person — the main agent could not allow it either.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "edit",
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "All in manual: an edit goes to the person.",
|
||||
"op": "call",
|
||||
"main_mode": "manual",
|
||||
"mode": "manual",
|
||||
"call": {
|
||||
"tool": "edit",
|
||||
"path": "src/a.ts"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Narrowed with no request options: what the main agent could allow is refused.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "manual",
|
||||
"call": {
|
||||
"tool": "edit",
|
||||
"path": "src/a.ts"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, and you may not ask for it: tell your parent what you need."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Narrowed with the kind in its options: it asks the main agent.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "manual",
|
||||
"request": [
|
||||
"write"
|
||||
],
|
||||
"call": {
|
||||
"tool": "edit",
|
||||
"path": "src/a.ts"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, but the main agent may: ask for it with team_request (the tool, the pattern, why), then try again once it allows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Narrowed, the kind not in its options.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "edit",
|
||||
"request": [
|
||||
"write"
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, and you may not ask for it: tell your parent what you need."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Narrowed, execute in its options: asks the main agent.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "edit",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, but the main agent may: ask for it with team_request (the tool, the pattern, why), then try again once it allows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A grant from the main agent lets the call run.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "edit",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"grants": [
|
||||
{
|
||||
"tool": "bash",
|
||||
"pattern": "git push *"
|
||||
}
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "run"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A grant for another pattern does not.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "edit",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"grants": [
|
||||
{
|
||||
"tool": "bash",
|
||||
"pattern": "git push *"
|
||||
}
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git commit -m x"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, but the main agent may: ask for it with team_request (the tool, the pattern, why), then try again once it allows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A grant never reaches past the main agent's own mode: what it would have to ask goes to the person.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "manual",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"grants": [
|
||||
{
|
||||
"tool": "bash",
|
||||
"pattern": "git push *"
|
||||
}
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Reading .env asks in every mode: it goes to the person.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "edit",
|
||||
"call": {
|
||||
"tool": "read",
|
||||
"path": ".env"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Reading .env under an auto main agent: a narrowed subagent with read in its options asks it.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "manual",
|
||||
"request": [
|
||||
"read"
|
||||
],
|
||||
"call": {
|
||||
"tool": "read",
|
||||
"path": ".env"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Your mode does not allow this, but the main agent may: ask for it with team_request (the tool, the pattern, why), then try again once it allows."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Plan mode's refusal is final: request options do not reach past it.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "plan",
|
||||
"request": [
|
||||
"execute"
|
||||
],
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "rm -rf build"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused",
|
||||
"text": "Plan mode: nothing changes but the plan. Put what this would do into the plan with plan_write or plan_update; it can be done once the person approves the plan."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "What the rules allow runs in every mode.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "plan",
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git status"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "run"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "The hardline refuses in every mode, auto included.",
|
||||
"op": "call",
|
||||
"main_mode": "auto",
|
||||
"mode": "auto",
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "rm -rf /"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Unattended: what would go to the person is refused.",
|
||||
"op": "call",
|
||||
"main_mode": "edit",
|
||||
"mode": "edit",
|
||||
"unattended": true,
|
||||
"call": {
|
||||
"tool": "bash",
|
||||
"line": "git push origin main"
|
||||
},
|
||||
"expect": {
|
||||
"answer": "refused"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "team_request: a tool whose risk class is not in the options is refused, naming them.",
|
||||
"op": "request",
|
||||
"request": [
|
||||
"write"
|
||||
],
|
||||
"tool": "bash",
|
||||
"expect": {
|
||||
"result": "You may not ask for bash: your request options are write."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "team_request: a kind in the options is asked, with the request's id.",
|
||||
"op": "request",
|
||||
"request": [
|
||||
"write",
|
||||
"execute"
|
||||
],
|
||||
"tool": "bash",
|
||||
"expect": {
|
||||
"result": "Asked the main agent (r1): you are told its decision. Carry on with what you can meanwhile."
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "The main agent made stricter: every subagent looser than its parent is made as strict as it, down the tree; a stricter one keeps its own.",
|
||||
"op": "switch",
|
||||
"agents": [
|
||||
{
|
||||
"name": "api",
|
||||
"parent": "lead",
|
||||
"mode": "auto"
|
||||
},
|
||||
{
|
||||
"name": "tests",
|
||||
"parent": "api",
|
||||
"mode": "edit"
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"parent": "lead",
|
||||
"mode": "plan"
|
||||
}
|
||||
],
|
||||
"main_from": "auto",
|
||||
"main_to": "manual",
|
||||
"expect": {
|
||||
"api": "manual",
|
||||
"tests": "manual",
|
||||
"docs": "plan"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "The main agent made looser: no subagent changes.",
|
||||
"op": "switch",
|
||||
"agents": [
|
||||
{
|
||||
"name": "api",
|
||||
"parent": "lead",
|
||||
"mode": "edit"
|
||||
}
|
||||
],
|
||||
"main_from": "edit",
|
||||
"main_to": "auto",
|
||||
"expect": {
|
||||
"api": "edit"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
{
|
||||
"about": "Progress (progress.md, spec 3.4.0): the text and the line every client draws for a progress object. `progress`: the object; `now`: the client's clock (Unix ms). Expect `text` — the phase's text from loop.json progress.texts, its fields filled (numbers written plainly: integers as they are, a rate with one decimal) — and `line` — `{{text}} · {{elapsed}}` with elapsed = now − since in whole seconds (5s, 1m 05s, 1h 02m), or the text alone for stopped and failed. retrying's `in` is counted down: in − floor((now − since) / 1000), never below 0. LLeMbas: services/progress.py; CLI: session/progress.ts.",
|
||||
"cases": [
|
||||
{
|
||||
"about": "Queued, nothing more known.",
|
||||
"progress": {
|
||||
"phase": "queued",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790405000,
|
||||
"expect": {
|
||||
"text": "Queued",
|
||||
"line": "Queued · 5s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Queued behind two turns.",
|
||||
"progress": {
|
||||
"phase": "queued",
|
||||
"since": 1762790400000,
|
||||
"ahead": 2
|
||||
},
|
||||
"now": 1762790465000,
|
||||
"expect": {
|
||||
"text": "Queued: 2 ahead",
|
||||
"line": "Queued: 2 ahead · 1m 05s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A one-request server answering another request.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_model",
|
||||
"since": 1762790400000,
|
||||
"model": "Qwen 27B",
|
||||
"reason": "busy"
|
||||
},
|
||||
"now": 1762790412400,
|
||||
"expect": {
|
||||
"text": "Waiting for Qwen 27B: it serves one request at a time and is answering another",
|
||||
"line": "Waiting for Qwen 27B: it serves one request at a time and is answering another · 12s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Every slot taken.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_model",
|
||||
"since": 1762790400000,
|
||||
"model": "coder",
|
||||
"reason": "slots"
|
||||
},
|
||||
"now": 1762790401000,
|
||||
"expect": {
|
||||
"text": "Waiting for coder: all its slots are in use",
|
||||
"line": "Waiting for coder: all its slots are in use · 1s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Another model on the one-model server.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_model",
|
||||
"since": 1762790400000,
|
||||
"model": "coder",
|
||||
"reason": "group"
|
||||
},
|
||||
"now": 1762790400000,
|
||||
"expect": {
|
||||
"text": "Waiting for coder: its server holds another model now",
|
||||
"line": "Waiting for coder: its server holds another model now · 0s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Loading.",
|
||||
"progress": {
|
||||
"phase": "loading_model",
|
||||
"since": 1762790400000,
|
||||
"model": "Gemma 12B"
|
||||
},
|
||||
"now": 1762794125000,
|
||||
"expect": {
|
||||
"text": "Loading Gemma 12B",
|
||||
"line": "Loading Gemma 12B · 1h 02m"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Reading the prompt: the percentage is floored.",
|
||||
"progress": {
|
||||
"phase": "reading_prompt",
|
||||
"since": 1762790400000,
|
||||
"done": 1999,
|
||||
"total": 3000
|
||||
},
|
||||
"now": 1762790402000,
|
||||
"expect": {
|
||||
"text": "Reading the prompt: 1999 / 3000 tokens (66%)",
|
||||
"line": "Reading the prompt: 1999 / 3000 tokens (66%) · 2s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Reading the prompt with no counts from the server.",
|
||||
"progress": {
|
||||
"phase": "reading_prompt",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790402000,
|
||||
"expect": {
|
||||
"text": "Reading the prompt",
|
||||
"line": "Reading the prompt · 2s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Thinking.",
|
||||
"progress": {
|
||||
"phase": "thinking",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790459999,
|
||||
"expect": {
|
||||
"text": "Thinking",
|
||||
"line": "Thinking · 59s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Writing, the rate with one decimal.",
|
||||
"progress": {
|
||||
"phase": "writing",
|
||||
"since": 1762790400000,
|
||||
"rate": 12.46
|
||||
},
|
||||
"now": 1762790404000,
|
||||
"expect": {
|
||||
"text": "Writing: 12.5 tok/s",
|
||||
"line": "Writing: 12.5 tok/s · 4s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Writing before a rate is measured.",
|
||||
"progress": {
|
||||
"phase": "writing",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790400400,
|
||||
"expect": {
|
||||
"text": "Writing",
|
||||
"line": "Writing · 0s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A tool with what it does.",
|
||||
"progress": {
|
||||
"phase": "running_tool",
|
||||
"since": 1762790400000,
|
||||
"tool": "bash",
|
||||
"what": "bun test"
|
||||
},
|
||||
"now": 1762790461000,
|
||||
"expect": {
|
||||
"text": "Running bash: bun test",
|
||||
"line": "Running bash: bun test · 1m 01s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A tool without a title.",
|
||||
"progress": {
|
||||
"phase": "running_tool",
|
||||
"since": 1762790400000,
|
||||
"tool": "recall"
|
||||
},
|
||||
"now": 1762790401000,
|
||||
"expect": {
|
||||
"text": "Running recall",
|
||||
"line": "Running recall · 1s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "An approval, naming the tool.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_person",
|
||||
"since": 1762790400000,
|
||||
"what": "approval",
|
||||
"tool": "bash"
|
||||
},
|
||||
"now": 1762790430000,
|
||||
"expect": {
|
||||
"text": "Waiting for you: allow bash?",
|
||||
"line": "Waiting for you: allow bash? · 30s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "An approval with no tool named.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_person",
|
||||
"since": 1762790400000,
|
||||
"what": "approval"
|
||||
},
|
||||
"now": 1762790400000,
|
||||
"expect": {
|
||||
"text": "Waiting for you: an approval",
|
||||
"line": "Waiting for you: an approval · 0s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "A question.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_person",
|
||||
"since": 1762790400000,
|
||||
"what": "question"
|
||||
},
|
||||
"now": 1762790403000,
|
||||
"expect": {
|
||||
"text": "Waiting for you: a question",
|
||||
"line": "Waiting for you: a question · 3s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "The plan.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_person",
|
||||
"since": 1762790400000,
|
||||
"what": "plan"
|
||||
},
|
||||
"now": 1762790403000,
|
||||
"expect": {
|
||||
"text": "Waiting for you: the plan",
|
||||
"line": "Waiting for you: the plan · 3s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Subagents.",
|
||||
"progress": {
|
||||
"phase": "waiting_for_subagents",
|
||||
"since": 1762790400000,
|
||||
"running": 3
|
||||
},
|
||||
"now": 1762790490000,
|
||||
"expect": {
|
||||
"text": "Waiting for subagents: 3 running",
|
||||
"line": "Waiting for subagents: 3 running · 1m 30s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Compacting.",
|
||||
"progress": {
|
||||
"phase": "compacting",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790407000,
|
||||
"expect": {
|
||||
"text": "Compacting the conversation",
|
||||
"line": "Compacting the conversation · 7s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Retrying: `in` counts down from since.",
|
||||
"progress": {
|
||||
"phase": "retrying",
|
||||
"since": 1762790400000,
|
||||
"reason": "502 Bad Gateway",
|
||||
"in": 10,
|
||||
"attempt": 2
|
||||
},
|
||||
"now": 1762790403000,
|
||||
"expect": {
|
||||
"text": "Retrying in 7 s: 502 Bad Gateway",
|
||||
"line": "Retrying in 7 s: 502 Bad Gateway · 3s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Retrying: never below 0.",
|
||||
"progress": {
|
||||
"phase": "retrying",
|
||||
"since": 1762790400000,
|
||||
"reason": "overloaded",
|
||||
"in": 2
|
||||
},
|
||||
"now": 1762790405000,
|
||||
"expect": {
|
||||
"text": "Retrying in 0 s: overloaded",
|
||||
"line": "Retrying in 0 s: overloaded · 5s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Stopped draws no elapsed time.",
|
||||
"progress": {
|
||||
"phase": "stopped",
|
||||
"since": 1762790400000
|
||||
},
|
||||
"now": 1762790405000,
|
||||
"expect": {
|
||||
"text": "Stopped",
|
||||
"line": "Stopped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Stopped by the person.",
|
||||
"progress": {
|
||||
"phase": "stopped",
|
||||
"since": 1762790400000,
|
||||
"reason": "person"
|
||||
},
|
||||
"now": 1762790405000,
|
||||
"expect": {
|
||||
"text": "Stopped: by you",
|
||||
"line": "Stopped: by you"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Stopped at the step limit.",
|
||||
"progress": {
|
||||
"phase": "stopped",
|
||||
"since": 1762790400000,
|
||||
"reason": "steps"
|
||||
},
|
||||
"now": 1762790400000,
|
||||
"expect": {
|
||||
"text": "Stopped: step limit",
|
||||
"line": "Stopped: step limit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"about": "Failed.",
|
||||
"progress": {
|
||||
"phase": "failed",
|
||||
"since": 1762790400000,
|
||||
"reason": "connection refused"
|
||||
},
|
||||
"now": 1762790405000,
|
||||
"expect": {
|
||||
"text": "Failed: connection refused",
|
||||
"line": "Failed: connection refused"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"about": "Teams (team.md, spec 3.2.0): one lead session's team, step by step, written from a reference model of the rules. `start`: the size setting `min` and `max`, `subagents` (enabled for the session; default true) and the chat model's `capacity` (models/schema.json: `parallel`, `single_session`; {} — no limit). The lead is `lead`; its first prompt is running as the case begins, and every agent is on the chat's model, and it is the only model there is (spec 3.3.0: other models are subagents.json's). Steps and what each answers: `offered` (`by` an agent, default lead) — `{tools, setting}`: the team tools listed for that agent, sorted, and whether the setting is shown; `call` (`by`, `tool`, `args`) — `{result, delivered}`: the call's answer word for word (null where an ordinary tool would run: the case looks only at whether it is refused), and what was delivered to whom by this step, `{name: [message, …]}`; `team_read` answers `{room, delivered}` instead, `room` being the messages it shows as `{n, from, to}` (the tree and the text format are loop.json team.read's, checked by each project's own tests); `task` runs a subagent that counts toward the size (and holds a slot) until `task_done` (`by`) — answers null; `finish` (`by`, `reply`, `reason`: stop by default, or steps, budget, `error — <text>`) — the agent's turn ends: a member's reply is its report — `{delivered}`; `set` (`min`, `max`, `capacity`: the person's setting or the model's metadata changed) — null; `person_stop` (`name`) — the person stopped that member in the UI — null; `user` — the person's message to the lead — `{note}`: the note on it (context.md §10), null when there is none; `state` — the team in tree order as `{name, manager, state}`: working, waiting (for a slot), finished, idle (the lead between turns). Delivering to a finished member or the idle lead wakes it (it is then working, or waiting when its model is full). LLeMbas: services/team.py; CLI: team/.",
|
||||
"about": "Teams (team.md, spec 3.2.0; the main agent and its tree, subagents.md §5–§13, spec 3.4.0 — a member's team_add is now the lead's with `parent`, and `offered` lists 3.4.0's tools): one lead session's team, step by step, written from a reference model of the rules. `start`: the size setting `min` and `max`, `subagents` (enabled for the session; default true) and the chat model's `capacity` (models/schema.json: `parallel`, `single_session`; {} — no limit). The lead is `lead`; its first prompt is running as the case begins, and every agent is on the chat's model, and it is the only model there is (spec 3.3.0: other models are subagents.json's). Steps and what each answers: `offered` (`by` an agent, default lead) — `{tools, setting}`: the team tools listed for that agent, sorted, and whether the setting is shown; `call` (`by`, `tool`, `args`) — `{result, delivered}`: the call's answer word for word (null where an ordinary tool would run: the case looks only at whether it is refused), and what was delivered to whom by this step, `{name: [message, …]}`; `team_read` answers `{room, delivered}` instead, `room` being the messages it shows as `{n, from, to}` (the tree and the text format are loop.json team.read's, checked by each project's own tests); `task` runs a subagent that counts toward the size (and holds a slot) until `task_done` (`by`) — answers null; `finish` (`by`, `reply`, `reason`: stop by default, or steps, budget, `error — <text>`) — the agent's turn ends: a member's reply is its report — `{delivered}`; `set` (`min`, `max`, `capacity`: the person's setting or the model's metadata changed) — null; `person_stop` (`name`) — the person stopped that member in the UI — null; `user` — the person's message to the lead — `{note}`: the note on it (context.md §10), null when there is none; `state` — the team in tree order as `{name, manager, state}`: working, waiting (for a slot), finished, idle (the lead between turns). Delivering to a finished member or the idle lead wakes it (it is then working, or waiting when its model is full). LLeMbas: services/team.py; CLI: team/.",
|
||||
"cases": [
|
||||
{
|
||||
"about": "Offered on a model that serves two requests at once: the lead has all four tools and the setting is shown.",
|
||||
@@ -19,9 +19,14 @@
|
||||
{
|
||||
"tools": [
|
||||
"team_add",
|
||||
"team_assign",
|
||||
"team_decide",
|
||||
"team_findings",
|
||||
"team_read",
|
||||
"team_replace",
|
||||
"team_send",
|
||||
"team_stop"
|
||||
"team_stop",
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
}
|
||||
@@ -43,9 +48,14 @@
|
||||
{
|
||||
"tools": [
|
||||
"team_add",
|
||||
"team_assign",
|
||||
"team_decide",
|
||||
"team_findings",
|
||||
"team_read",
|
||||
"team_replace",
|
||||
"team_send",
|
||||
"team_stop"
|
||||
"team_stop",
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
}
|
||||
@@ -113,9 +123,14 @@
|
||||
{
|
||||
"tools": [
|
||||
"team_add",
|
||||
"team_assign",
|
||||
"team_decide",
|
||||
"team_findings",
|
||||
"team_read",
|
||||
"team_replace",
|
||||
"team_send",
|
||||
"team_stop"
|
||||
"team_stop",
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
}
|
||||
@@ -200,9 +215,14 @@
|
||||
{
|
||||
"tools": [
|
||||
"team_add",
|
||||
"team_assign",
|
||||
"team_decide",
|
||||
"team_findings",
|
||||
"team_read",
|
||||
"team_replace",
|
||||
"team_send",
|
||||
"team_stop"
|
||||
"team_stop",
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
},
|
||||
@@ -228,7 +248,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"about": "A member that may not lead has team_send and team_read; one that may lead has all four.",
|
||||
"about": "A subagent has team_whoami, team_read, team_send, team_findings and team_finish; a sub-manager the same — it adds nothing (spec 3.4.0).",
|
||||
"start": {
|
||||
"min": 1,
|
||||
"max": 4,
|
||||
@@ -279,17 +299,21 @@
|
||||
},
|
||||
{
|
||||
"tools": [
|
||||
"team_findings",
|
||||
"team_finish",
|
||||
"team_read",
|
||||
"team_send"
|
||||
"team_send",
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
},
|
||||
{
|
||||
"tools": [
|
||||
"team_add",
|
||||
"team_findings",
|
||||
"team_finish",
|
||||
"team_read",
|
||||
"team_send",
|
||||
"team_stop"
|
||||
"team_whoami"
|
||||
],
|
||||
"setting": true
|
||||
}
|
||||
@@ -392,7 +416,7 @@
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"note": "<session-note>\nThe team may have 3 to 5 agents, you included.\nWork through a team from the start: you lead, and members do the work — at least 2 of them.\n</session-note>"
|
||||
"note": "<session-note>\nThe team may have 3 to 5 agents, you included.\nWork through subagents from the start: you lead, and they do the work. The person opened 2 slots for them: fill them with team_add.\n</session-note>"
|
||||
},
|
||||
{
|
||||
"result": "You lead a team: give this to a member (team_add or team_send).",
|
||||
@@ -458,7 +482,7 @@
|
||||
],
|
||||
"expect": [
|
||||
{
|
||||
"note": "<session-note>\nThe team may have 2 to 2 agents, you included.\nWork through a team from the start: you lead, and members do the work — at least 1 of them.\n</session-note>"
|
||||
"note": "<session-note>\nThe team may have 2 to 2 agents, you included.\nWork through subagents from the start: you lead, and they do the work. The person opened 1 slots for them: fill them with team_add.\n</session-note>"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -632,7 +656,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"about": "The size is across the whole tree: a member that leads adds within the same max.",
|
||||
"about": "The size is across the whole tree: subagents placed under a sub-manager count within the same max.",
|
||||
"start": {
|
||||
"min": 1,
|
||||
"max": 4,
|
||||
@@ -653,12 +677,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "backend",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "db",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "backend"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -673,12 +698,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "backend",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "api",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "backend"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1538,7 +1564,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"about": "A member works; a member that leads becomes a manager when it adds one; stopping all its members makes the lead a worker again (min 1).",
|
||||
"about": "A subagent works; a sub-manager becomes a manager when one is placed under it; stopping them all makes the lead a worker again (min 1).",
|
||||
"start": {
|
||||
"min": 1,
|
||||
"max": 6,
|
||||
@@ -1565,12 +1591,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1805,12 +1832,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2009,22 +2037,24 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "db",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2396,13 +2426,14 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part.",
|
||||
"goal": "The REST API"
|
||||
"goal": "The REST API",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2670,7 +2701,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"about": "Stopping a member stops its subtree; they leave the team, and their names are free again. Only members under the caller may be stopped.",
|
||||
"about": "Stopping is the main agent's: a subagent's team_stop is refused. Stopping a subagent stops its subtree; they leave the team, and their names are free again.",
|
||||
"start": {
|
||||
"min": 1,
|
||||
"max": 8,
|
||||
@@ -2691,33 +2722,36 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part.",
|
||||
"lead": true
|
||||
"lead": true,
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "routes",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "auth",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "routes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "db",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2756,7 +2790,7 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_stop",
|
||||
"args": {
|
||||
"name": "routes"
|
||||
@@ -2767,12 +2801,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "auth",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2817,15 +2852,15 @@
|
||||
"delivered": {}
|
||||
},
|
||||
{
|
||||
"result": "web is not under you: you can stop only the members you lead, directly or through your members.",
|
||||
"result": "Only the main agent adds, assigns, replaces and stops subagents: ask it (team_send to lead).",
|
||||
"delivered": {}
|
||||
},
|
||||
{
|
||||
"result": "api is not under you: you can stop only the members you lead, directly or through your members.",
|
||||
"result": "Only the main agent adds, assigns, replaces and stops subagents: ask it (team_send to lead).",
|
||||
"delivered": {}
|
||||
},
|
||||
{
|
||||
"result": "No agent called ghost in this team. The team: lead, api, routes, auth, db, web.",
|
||||
"result": "Only the main agent adds, assigns, replaces and stops subagents: ask it (team_send to lead).",
|
||||
"delivered": {}
|
||||
},
|
||||
{
|
||||
@@ -2900,12 +2935,13 @@
|
||||
},
|
||||
{
|
||||
"op": "call",
|
||||
"by": "api",
|
||||
"by": "lead",
|
||||
"tool": "team_add",
|
||||
"args": {
|
||||
"name": "routes",
|
||||
"role": "owns a part",
|
||||
"task": "Do the part."
|
||||
"task": "Do the part.",
|
||||
"parent": "api"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user