-
Notifications
You must be signed in to change notification settings - Fork 0
docs: add mcp whitelist, maxturn, and halt/warn hook patterns #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # maxturns bounded tasks pattern | ||
|
|
||
| set an explicit `maxTurns` on any agent whose task has a known completion boundary. | ||
|
|
||
| ## problem | ||
|
|
||
| an agent without a `maxTurns` ceiling will continue until it decides it is done, hits a context limit, or enters a loop. for agents with open-ended research tasks, this is appropriate — stopping too early loses value. for agents with bounded, verifiable tasks (file a PR, run a validation, scan a directory), an unbounded run is a risk: loop states persist, token costs accumulate, and the entropy anchor gets no signal that something went wrong. | ||
|
|
||
| a bounded agent that hits `maxTurns` surfaces as a failed run with a clear count. an unbounded agent that loops surfaces as a timeout or a confusing partial result. | ||
|
|
||
| ## pattern | ||
|
|
||
| assess task boundedness before setting the field: | ||
|
|
||
| | task type | maxTurns | rationale | | ||
| | --------------------------------------------------- | -------- | -------------------------------------------------------- | | ||
| | single git operation (commit, PR, branch) | 20–40 | four to eight tool calls per step, bounded by repo state | | ||
| | file audit / scan (read-only pass over known scope) | 15–25 | bounded by file count, not open-ended | | ||
| | schema validation | 10–15 | deterministic, few steps | | ||
| | UX test session (multi-step automation) | 40–60 | bounded by test script steps, not research depth | | ||
| | deep research or open-ended synthesis | omit | value scales with depth; early cutoff loses signal | | ||
| | session anchor / orchestrator | omit | must remain alive for the full session | | ||
|
|
||
| ### Claude Code format | ||
|
|
||
| in a theseus agent definition (`.claude/agents/*.md` frontmatter): | ||
|
|
||
| ```yaml | ||
| --- | ||
| name: hs-shannon-theseus-orin-github-ops | ||
| model: claude-sonnet-4-6 | ||
| maxTurns: 40 | ||
| --- | ||
| ``` | ||
|
|
||
| ### kiro-cli format | ||
|
|
||
| kiro does not expose a `maxTurns` field in agent JSON. bounded execution in kiro is enforced by the DUTIES contract (`DUTIES.md` exit conditions) and the poltergeist anchor's supervision pattern. | ||
|
|
||
| ## calibration notes | ||
|
|
||
| - `maxTurns` counts agent turns (model responses), not tool calls. a single turn can contain multiple tool calls. | ||
| - set it 20–30% above the expected turn count for the happy path. too tight causes spurious failures on minor detours; too loose defeats the purpose. | ||
| - after a `maxTurns` failure, check the transcript for loop patterns before raising the ceiling — the limit often surfaces a real problem. | ||
|
|
||
| ## applied across the heraldstack | ||
|
|
||
| | repo | agent | maxTurns | | ||
| | -------------------------------- | ----------------------------------------------- | -------- | | ||
| | shannon-claude-code-cli | hs-shannon-theseus-orin-github-ops | 40 | | ||
| | ux-testing-moodle-uploader | hs-shannon-theseus-liora-ux-field-tester | 60 | | ||
| | ux-testing-moodle-uploader | hs-shannon-theseus-stratia-ux-reviewer | 20 | | ||
| | chrome-extension-moodle-uploader | hs-shannon-theseus-orin-github-ops (ux variant) | 40 | | ||
|
|
||
| ## reference | ||
|
|
||
| - source pattern: shannon audit (2026-04-11), propagated to ux-testing PR #14, chrome-extension PR #503 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # mcp server whitelist pattern | ||
|
|
||
| declare an explicit, minimal mcpServers block in every agent definition — never inherit a global set by omission. | ||
|
|
||
| ## problem | ||
|
|
||
| when an agent definition omits the `mcpServers` field, the harness loads every server configured for the session. a research agent inherits a filesystem MCP it never calls. a REST-only subagent inherits valkey, qdrant, and github tools that sit idle but consume context and expand the attack surface. the cost is invisible until you audit token usage or trace an unexpected tool call in a session log. | ||
|
|
||
| in Claude Code agent definitions, the `mcpServers` field is optional. omitting it does not mean "no servers" — it means "inherit all servers from the session's `.mcp.json`." | ||
|
|
||
| ## pattern | ||
|
|
||
| every agent definition declares its MCP server list explicitly. | ||
|
|
||
| ### REST-only agents (no MCP tools needed) | ||
|
|
||
| ```yaml | ||
| mcpServers: [] | ||
| ``` | ||
|
|
||
| an empty array is unambiguous: no servers load for this agent. applies to agents that work entirely through native tools (Bash, Read, Grep, Edit, Write) or make calls over HTTP without needing an MCP server. | ||
|
|
||
| examples: `hs-shannon-theseus-orin-github-ops` (uses `gh` CLI via Bash), `hs-shannon-theseus-stratia-codebase-mapper` (read-only native tools), validation agents whose output is pure reasoning. | ||
|
|
||
| ### agents with bounded tool needs | ||
|
|
||
| list only what the agent actually calls: | ||
|
|
||
| ```yaml | ||
| mcpServers: | ||
| - qdrant-shared | ||
| - context7 | ||
| ``` | ||
|
|
||
| not the full session set. if the agent does one semantic query and nothing else, it gets one server. | ||
|
|
||
| ### agents that legitimately need the full session set | ||
|
|
||
| leave the field absent — but document why. add a comment or a note in the agent's `## mcp` section explaining that full server inheritance is intentional. this makes the omission a deliberate choice rather than an oversight. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This section tells readers to leave Useful? React with 👍 / 👎. |
||
|
|
||
| ## how to audit | ||
|
|
||
| run a pass over all agent definitions in `.claude/agents/`: | ||
|
|
||
| ```bash | ||
| grep -L "mcpServers" .claude/agents/*.md | ||
| ``` | ||
|
|
||
| files missing `mcpServers` are candidates for review. for each: check whether the agent calls MCP tools. if not, add `mcpServers: []`. if it does, enumerate the specific servers it needs. | ||
|
|
||
| also check for dead `disallowedTools` blocks that were added to compensate for inherited servers. when `mcpServers: []` is explicit, there is nothing to disallow — remove the block. | ||
|
|
||
| ## applied across the heraldstack | ||
|
|
||
| | repo | agents updated | result | | ||
| | -------------------------------- | --------------------------------------- | ---------------------------------------- | | ||
| | shannon-claude-code-cli | 6 REST-only agents | mcpServers: [] + disallowedTools removed | | ||
| | ux-testing-moodle-uploader | 2 agents (liora, orin) | mcpServers: [] | | ||
| | chrome-extension-moodle-uploader | 6 REST-only agents, 1 chrome-only agent | mcpServers: [] / ["chrome-devtools"] | | ||
|
|
||
| ## reference | ||
|
|
||
| - source pattern: shannon audit (2026-04-11), propagated to ux-testing PR #14, chrome-extension PR #503 | ||
| - first captured: heraldstack/shannon-claude-code-cli issue #52 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new guidance describes this behavior as a “hard block,” but the provided implementation only emits
systemMessageJSON and never exits non-zero; later text also says stdout is injected into context before turn one. That means sessions continue even when critical services are down, so operators relying on this as an enforced halt can still run tasks against unavailable infrastructure.Useful? React with 👍 / 👎.