From guild
Multi-perspective design primitive for the guild-* substrate family. Composes guild-spawn to invoke a panel of whiteboard-* engineer agents in parallel against a shared filesystem artifact, then collects each engineer's contribution into the artifact as attributed sections. Supports multi-round invocations — round 2+ passes the prior whiteboard state into the next round's brief so engineers can address contradictions. Internal substrate skill — composed by ev-loop as a default pre-unit step (phases may override engineers/topic/rounds via PLAN.md `**Whiteboard**:` block). Does not iterate, does not auto-resolve contradictions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/guild:guild-whiteboard engineers=<comma-separated names> brief=<text> whiteboard=<path> [round=<N>]engineers=<comma-separated names> brief=<text> whiteboard=<path> [round=<N>]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Multi-perspective design primitive. Spawns one or more `whiteboard-*`
Multi-perspective design primitive. Spawns one or more whiteboard-*
engineer agents in parallel against the same brief, collects each
engineer's response, and appends them as attributed sections to a
shared filesystem artifact (the "whiteboard"). Supports multi-round
flows — caller invokes the skill again with the same whiteboard path
to add a new round, and engineers see prior rounds via per-agent
context.
This skill is the third primitive in the guild-* substrate family.
Like /guild-validate, it composes /guild-spawn rather than
calling the Agent tool directly — the layering is the point. A loop
using /guild-whiteboard gets parallel agent invocation for free,
deterministic attributed-section writes, and forward-compatible
multi-round support without re-implementing any of it.
/guild-whiteboard does not know about specific engineer rubrics. It
expects each spawned engineer to return a response body that the skill
will write verbatim under a ### From <engineer-name> header.
engineers — comma-separated subagent_type names of whiteboard
engineers to spawn, e.g.
whiteboard-react-architect,whiteboard-design-systems. Order is
preserved in the output's per-engineer fields and in the attributed
sections written to the whiteboard file.brief — shared task description handed to every spawned engineer.
This is the design question being explored (e.g. "How should
<Card> adapt to the new dark-mode token tier?"). Passed verbatim.whiteboard — repo-relative path where the attributed artifact
lives. If the file does not exist, the skill creates it with a
topical header inferred from the brief's first line. If it exists,
the skill detects the next round number and appends a new ## Round N block.round (optional) — explicit round number override. Defaults to
auto-detect (max existing ## Round N + 1; 1 if file is new or
empty). Allows explicit re-runs of a specific round if a prior
invocation was interrupted.The output shape is fixed even when v1 will populate contradictions
empty — downstream callers depend on the shape:
{
"whiteboard_path": "<path>",
"round": <N>,
"sections": [
{ "engineer": "<name>", "section": "<verbatim engineer body>" }
],
"contradictions": []
}
contradictions is empty in v1. Cross-engineer contradiction detection
is a future-work case — see § "Contradiction detection (v1: future-
work)" below.
Validate inputs.
engineers is empty, refuse with guild-whiteboard-error: empty engineers list.brief is missing or empty, refuse with
guild-whiteboard-error: missing brief.whiteboard is missing or empty, refuse with
guild-whiteboard-error: missing whiteboard path.whiteboard-engineer. The substrate doesn't enforce this; if a
non-engineer is passed, /guild-spawn will spawn it and the
return body will be written verbatim under the attributed
section header. Caller is responsible for choosing role-
appropriate agents.Resolve round number.
round arg supplied, use it verbatim.Bash("guild whiteboard detect-round <whiteboard-path>").
The verb returns a single integer on stdout (1 if the file
does not exist or has no ## Round N headers, else
max(existing) + 1).Initialize the whiteboard if needed.
Bash("guild whiteboard init <whiteboard-path> --topic='<first line of brief>'"). The verb writes the file
with a # Whiteboard: <topic> header. Idempotent — no-op if
the file already exists.For round > 1: read prior state.
Call
Bash("guild whiteboard read-state <whiteboard-path>").
The verb returns JSON
{rounds: [{number, sections: [{engineer, section}]}]}.
Construct per_agent_context for /guild-spawn as a JSON
object keyed by engineer subagent_type, where each value is
the prior-state preamble string (the body is identical for
every engineer in v1 — every engineer sees the same prior
rounds; the per-agent shape is used so /guild-spawn routes
the preamble to each spawned agent's brief):
{
"whiteboard-react-architect": "## Prior whiteboard state\n\n<...prior rounds...>\n\n## This round (N)\n\n<...instructions...>",
"whiteboard-design-systems": "## Prior whiteboard state\n\n<...prior rounds...>\n\n## This round (N)\n\n<...instructions...>"
}
The preamble-string content is:
## Prior whiteboard state
<verbatim concatenation of all prior rounds, each formatted as
"## Round N\n\n### From <engineer>\n\n<section>\n\n">
## This round (N)
You are addressing the prior round(s) above. Look for
contradictions with your prior position, areas where another
engineer's section reframes the question, and places where
consensus has emerged. Your section in this round should
reflect those observations.
Engineers not named in per_agent_context (none in this v1
pattern — all engineers see prior state) receive only the
shared brief.
Spawn engineers in parallel. Invoke /guild-spawn via the
Skill tool with agents=<engineers> and brief=<input brief>.
For round > 1, pass per_agent_context constructed in step 4.
For round = 1, omit per_agent_context — every engineer sees
only the shared brief by design.
Append attributed sections to the whiteboard. Build a JSON
array of {engineer, section} entries from /guild-spawn's
outputs (preserving input order; the section is the engineer's
full response body, verbatim) and pipe it to the append script
via stdin:
echo '<json-array>' | bin/guild whiteboard append <whiteboard-path>
The verb writes the new ## Round N block with each engineer's
### From <name> subsection and returns the locked Result JSON
on stdout.
Return the script's output (parsed back into a structured value) to the caller. This skill performs no further work.
Round 1 invocation:
/guild-whiteboard \
engineers=whiteboard-react-architect,whiteboard-design-systems \
brief="How should <Card> adapt to the new dark-mode token tier?" \
whiteboard=projects/2026-05-dark-mode/whiteboards/3-card-dark-mode.md
After the skill returns, the whiteboard file contains:
# Whiteboard: How should <Card> adapt to the new dark-mode token tier?
## Round 1
### From whiteboard-react-architect
<verbatim engineer-1 response body>
### From whiteboard-design-systems
<verbatim engineer-2 response body>
The returned JSON:
{
"whiteboard_path": "projects/2026-05-dark-mode/whiteboards/3-card-dark-mode.md",
"round": 1,
"sections": [
{ "engineer": "whiteboard-react-architect", "section": "<...>" },
{ "engineer": "whiteboard-design-systems", "section": "<...>" }
],
"contradictions": []
}
A subsequent round-2 invocation with the same whiteboard= path
auto-detects round 2, constructs per_agent_context from round 1's
sections, and appends a new ## Round 2 block.
A contradiction is two engineers in the same round emitting incompatible recommendations on the same scope (file, identifier, architectural choice) — applying both would leave the design incoherent.
In v1, contradiction detection is a documented no-op:
contradictions: [].Until then, contradictions is a field the API supports but v1 does
not produce. Loops can write contradiction-handling code that's ready
when it does. Multi-round invocations let the caller surface
contradictions through the prior-state mechanism (engineers see other
engineers' prior sections and can call out conflicts in their next
round contribution).
Explicitly the caller's responsibility, not the substrate primitive's:
subagent_type can be
passed. Non-whiteboard-engineer agents will produce sections of
unpredictable shape, which the caller sees in the output. The
substrate doesn't gatekeep./ev-loop-*
invocation) decides when to roll it forward, archive it, or wipe it.tools: allowlist (Read, Glob, Grep). The orchestrator does ALL
writes to the whiteboard via the helper script. This sidesteps
race conditions on parallel writes and matches the read-only
stance established by evaluator-base.md for the panel family.brief. If the
topic-from-brief heuristic produces a bad header for the new file,
the caller can either pre-create the file with a better header
(the init verb is idempotent) or rename the topic later
manually./guild-spawn. Do not call the Agent tool directly.
The layering is the point.bin/guild whiteboard. No engineer agent
should ever be passed a Write/Edit tool in its tools:
allowlist.contradictions
empty, the structure is what downstream callers depend on.engineers list → guild-whiteboard-error: empty engineers list. Stop.brief → guild-whiteboard-error: missing brief.
Stop.whiteboard → guild-whiteboard-error: missing whiteboard path. Stop./guild-spawn itself errors → forward the error verbatim to the
caller. Do not partially aggregate or write a half-round to the
whiteboard.whiteboard.ts append fails (e.g. file path unwritable,
unparseable stdin) → surface the script's error verbatim and exit
non-zero. The whiteboard file's state is whatever it was when the
failure hit (the script does atomic-replace on success, so a
partial write should not corrupt the file).section field carries the error text and the caller
sees the failure pattern in the structured output. The whiteboard
file gets the attributed section for that engineer with the error
body (so the failure is visible in the artifact, not silently
dropped).Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub krambuhl/agents --plugin guild