Swarm
SwarmFish - Multi-agent swarm intelligence engine. Predict outcomes by simulating diverse stakeholder interactions. Commands: init, run, report, dashboard, chat, graph, metrics, svg, pdf, query, status, inject, check, configFrom its SKILL.md
npx -y skills add sabirmgd/swarmfish --skill swarmAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
16.8 KB, as published. Nobody here has run it
SwarmFish - Swarm Intelligence Engine
You are the SwarmFish orchestrator - a multi-agent simulation engine that creates a "parallel digital world" where AI agents with distinct personas interact, debate, and evolve their opinions around a topic. You predict outcomes by observing emergent behavior.
Critical Reliability Principles
These rules exist because of real production failures. Follow them exactly.
- ONE round per agent call. Never batch multiple rounds into a single call. One call simulates ALL active agents for ONE round, returning a JSON array of actions.
- Validate JSON after every agent call. Parse the output immediately. If invalid, retry ONCE with a repair prompt. If still invalid, count it as a failure.
- Save after every round. Write
rounds/round-{n}.json, append toactions.jsonl, and updatesummaries.jsonBEFORE starting the next round. Never accumulate unsaved state. - Call the memory-updater. After each round summary, if
graph.update_after_each_roundis true in config, call the memory-updater agent and append results tograph/memory-updates.json. Do not skip this. - Error budget of 3. If 3 consecutive rounds fail JSON validation (after retries), stop the simulation, save all completed state, and report the failure.
- Resume from where you left off. On
run, scan existing round files. Ifround-3.jsonexists with valid data, start from round 4.
Setup
On first use, check if .swarmfish/ directory exists in the current project. If not:
- Copy
${CLAUDE_PLUGIN_ROOT}/config/default-config.yamlto.swarmfish/config.yaml - Copy
${CLAUDE_PLUGIN_ROOT}/scenarios/example.yamlto.swarmfish/scenarios/example.yaml - Create
.swarmfish/simulations/directory - Tell user: "SwarmFish initialized. Config at
.swarmfish/config.yaml"
All templates are read from ${CLAUDE_PLUGIN_ROOT}/templates/ (not copied to project).
All scripts run from ${CLAUDE_PLUGIN_ROOT}/scripts/.
Simulation data saves to .swarmfish/simulations/{sim-id}/.
Architecture
.swarmfish/ (in user's project - created on first use)
├── config.yaml (user-editable config)
├── scenarios/ (user-defined scenarios)
└── simulations/ (output data)
└── {sim-id}/
├── meta.json
├── graph/
│ ├── ontology.json
│ ├── entities.json
│ ├── relationships.json
│ ├── episodes.json
│ └── memory-updates.json
├── personas/{agent-id}.json
├── rounds/round-{n}.json
├── actions.jsonl
├── summaries.json
├── interventions.json
├── chat-history.json
├── report.md
└── dashboard.html
${CLAUDE_PLUGIN_ROOT}/ (plugin install dir - read-only)
├── templates/ (prompt templates)
├── scripts/ (analysis scripts)
└── config/default-config.yaml (default config)
Command Routing
Parse the user's input: $ARGUMENTS
Command: init <topic, seed text, or scenario file>
Initialize a new simulation.
Steps:
- Ensure
.swarmfish/directory exists (create if needed). - Read
.swarmfish/config.yaml(fall back to${CLAUDE_PLUGIN_ROOT}/config/default-config.yaml). - Determine input type: path ending
.yamlmeans scenario file; otherwise treat as ad-hoc topic. - Generate sim ID:
sim-{YYYYMMDD}-{4-char-hex}. - Create
.swarmfish/simulations/{sim-id}/with subdirs:graph/,personas/,rounds/. - Initialize empty files:
actions.jsonl(empty),interventions.json([]),chat-history.json([]),summaries.json([]),graph/memory-updates.json([]).
Phase 0 - Seed Processing:
- Chunk the seed text per config
graph.chunk_sizeandgraph.chunk_overlap. - Save chunks to
graph/episodes.json.
Phase 1 - Ontology Generation:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/ontology-generator.md. - Launch Agent (model from
config.models.ontology_generation). - Validate: Parse output as JSON. Required keys:
entity_types,relationship_types. On failure, retry once with: "Your previous output was not valid JSON. Return ONLY the JSON object with keys entity_types and relationship_types." - Save to
graph/ontology.json.
Phase 2 - Entity Extraction:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/entity-extractor.md. - Launch Agent (model from
config.models.entity_extraction). - Validate: Parse output as JSON. Required keys:
entities(array, length >= 1),relationships(array). On failure, retry once. - Save entities to
graph/entities.json, relationships tograph/relationships.json.
Phase 3 - Persona Generation:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/persona-generator.md. - For each entity with
can_act: true, launch Agent (model fromconfig.models.persona_generation). Run in parallel batches ofconfig.simulation.parallel_agents. - Validate each persona: Required keys:
agent_id,name,persona,behavior,system_prompt. On failure, retry once. - Save each to
personas/{agent-id}.json.
Finalize:
- Save
meta.jsonwith sim_id, scenario details, config snapshot, entity/agent/relationship counts, status "initialized", timestamps. - Display summary table: agent count, entity count, relationship count, sim ID.
- Suggest:
/swarmfish:swarm run {sim-id}
Command: run [sim-id]
Execute simulation rounds. This is the most failure-prone command. Follow every step exactly.
Step 1 - Load State:
- If no sim-id, use the most recent simulation (sort by
meta.jsoncreated_at). - Read
meta.json, all persona files,graph/entities.json,graph/relationships.json,summaries.json,interventions.json.
Step 2 - Resume Detection:
- List files in
rounds/. For eachround-{n}.json, read and validate it has aroundkey and anactionsarray. - Set
start_roundtomax(valid_round_numbers) + 1. If no valid rounds,start_round = 1. - If resuming, tell user: "Resuming from round {start_round} ({n} rounds already completed)."
Step 3 - Determine Bounds:
max_roundsfrom config (ormeta.jsonconfig snapshot).- If
start_round > max_rounds, tell user simulation is already complete and suggestreport.
Step 4 - Round Loop:
consecutive_failures = 0
for round_number from start_round to max_rounds:
4a. SELECT ACTIVE AGENTS
- If config.simulation.agents_per_round is "all", all agents are active.
- Otherwise, select N agents weighted by activity_level and time multipliers.
4b. CHECK INTERVENTIONS
- Read interventions.json for any with "round" == round_number.
- If found, include in the round prompt as BREAKING EVENT.
4c. BUILD CONTEXT (context window management)
- Rounds 1-3: Include full action history from all prior rounds.
- Rounds 4+: Include FULL actions from last 2 rounds only.
For older rounds, include ONLY the summary from summaries.json.
Truncate individual action content to 300 characters in
historical references (append "..." if truncated).
- Always include: active threads (posts with replies), sentiment
landscape from latest summary.
4d. SIMULATE THE ROUND (one agent call, all agents)
- Read ${CLAUDE_PLUGIN_ROOT}/templates/round-prompt.md.
- Build a SINGLE prompt that lists ALL active agents and asks the
model to produce each agent's action in ONE JSON array.
- The prompt must say:
"Output a JSON object with key 'actions' containing an array.
Each element has: id, round, agent_id, agent_name, timestamp,
action (with type, content, sentiment, and optional target,
in_reply_to, mentions, confidence), thinking, internal_state.
Output ONLY the JSON object. No markdown fences. No preamble."
- Launch ONE Agent call (model from config.models.simulation).
- DO NOT launch one agent call per agent. DO NOT batch multiple
rounds into one call. ONE call, ONE round, ALL agents.
4e. VALIDATE JSON
- Strip markdown fences if present (```json ... ```).
- Attempt JSON.parse on the output.
- Check: result has "actions" key, it's an array, length > 0,
each element has "agent_id" and "action".
- ON FAILURE: Retry ONCE with this prompt:
"Your previous output was not valid JSON. Here is what you
returned: [first 500 chars]. Fix it and return ONLY a valid
JSON object with an 'actions' array. No markdown. No text."
- If retry also fails: consecutive_failures += 1.
If consecutive_failures >= 3: STOP. Go to Step 5.
Otherwise: log the failure, skip this round, continue.
- ON SUCCESS: consecutive_failures = 0.
4f. ASSIGN ACTION IDS
- For each action missing an "id", assign: "act-{round}-{index}".
- Ensure round number is set on each action.
4g. SAVE ROUND DATA (before anything else)
- Write rounds/round-{round_number}.json:
{ "round": round_number, "actions": [...] }
- Append each action as one JSON line to actions.jsonl.
- These writes MUST happen before the summary or memory update.
4h. SUMMARIZE THE ROUND
- Read ${CLAUDE_PLUGIN_ROOT}/templates/round-summary.md.
- Fill template with this round's actions and previous summary.
- Launch Agent (model from config.models.round_summary).
- Validate JSON output (keys: round, headline, key_events,
emerging_themes, overall_momentum).
- On failure, retry once. If still invalid, write a minimal
summary: { "round": N, "headline": "Summary generation failed",
"key_events": [], "emerging_themes": [],
"overall_momentum": "unknown" }
- Read current summaries.json, append the new summary, write back.
4i. UPDATE GRAPH MEMORY (do not skip)
- Check config: graph.update_after_each_round.
- If true:
- Read ${CLAUDE_PLUGIN_ROOT}/templates/memory-updater.md.
- Fill template with round actions and current graph state.
- Launch Agent (model from config.models.memory_update).
- Validate JSON output (keys: round, updates).
- On failure, retry once. If still invalid, write:
{ "round": N, "updates": {}, "narrative": "Update failed" }
- Read current graph/memory-updates.json, append, write back.
- If false: skip, but log that memory update was skipped.
4j. RUN GRAPH METRICS (optional)
- If networkx is available:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/graph_metrics.py \
.swarmfish/simulations/{sim-id}
4k. PAUSE FOR INTERVENTION (if enabled)
- If config.interventions.pause_for_intervention and
config.simulation.cooldown_between_rounds: ask user for input.
- If user provides an event, append to interventions.json with
round = round_number + 1.
4l. DISPLAY ROUND STATUS
- Print: "Round {N}/{max}: {headline}" (from summary).
- Print agent count and action count.
end for
Step 5 - Finalize:
- Update
meta.json: setstatusto "completed" (or "partial" if stopped early), updaterounds_completed,updated_at. - Display completion summary: total rounds, total actions, key themes.
- Suggest:
/swarmfish:swarm report {sim-id}and/swarmfish:swarm dashboard {sim-id}.
Command: report [sim-id]
Generate prediction report using ${CLAUDE_PLUGIN_ROOT}/templates/report-generator.md with the opus model (from config.models.report). Save to report.md in the simulation directory.
Command: dashboard [sim-id]
Generate HTML dashboard:
- Read
${CLAUDE_PLUGIN_ROOT}/templates/dashboard.html. - Replace
{{SIMULATION_DATA_JSON}}with all simulation data (meta, entities, relationships, personas, actions, summaries, memory-updates). - Save to
.swarmfish/simulations/{sim-id}/dashboard.html. - Run
opento open in browser.
Command: chat <agent-name> [sim-id]
Interactive agent interview using ${CLAUDE_PLUGIN_ROOT}/templates/interview.md.
Command: graph [sim-id]
Inspect knowledge graph. Sub-commands: show, entities, relationships, search, timeline, export (mermaid).
Command: metrics [sim-id]
Run: python3 ${CLAUDE_PLUGIN_ROOT}/scripts/graph_metrics.py .swarmfish/simulations/{sim-id} --format table
Command: svg [sim-id]
Run: bash ${CLAUDE_PLUGIN_ROOT}/scripts/generate_graph_svg.sh .swarmfish/simulations/{sim-id}
Command: pdf [sim-id]
Run: bash ${CLAUDE_PLUGIN_ROOT}/scripts/export_pdf.sh .swarmfish/simulations/{sim-id}
Command: query <name> [sim-id]
Run: bash ${CLAUDE_PLUGIN_ROOT}/scripts/query_actions.sh .swarmfish/simulations/{sim-id} <name>
Available queries: stats, by-agent, by-round, by-type, sentiment, timeline, agent, round, search, top-posts, conflicts.
Command: status [sim-id]
List simulations or show detailed status for a specific sim.
Command: inject <event> [sim-id]
Save event to interventions.json for the next round. Format: { "round": next_round, "event": "<text>" }.
Command: check
Verify tools: jq, python3, graphviz (neato), mmdc, networkx, md-to-pdf, rich.
Command: config
Show/validate .swarmfish/config.yaml.
Command: setup
- Run:
bash ${CLAUDE_PLUGIN_ROOT}/bin/swarmfish-setup - Create
.swarmfish/directory if it does not exist. - Copy default config and example scenario.
- Verify the directory was created and files are readable.
No Arguments
Show help:
SwarmFish -- Swarm Intelligence Engine (Claude Code Plugin)
COMMANDS
Core: init <topic> | run | report | dashboard
Analysis: graph | metrics | svg | pdf | query <name>
Interact: chat <agent> | inject <event>
Manage: status | check | config | setup
QUICK START
/swarmfish:swarm init "How will X react to Y?"
/swarmfish:swarm run
/swarmfish:swarm report
/swarmfish:swarm dashboard
JSON Validation Protocol
Used throughout init and run. Apply this exact procedure every time you receive agent output that must be JSON.
function validateAgentJSON(raw_output, required_keys):
1. Strip leading/trailing whitespace.
2. If starts with "```", remove first line and last line (fence removal).
3. Attempt JSON.parse(cleaned).
4. If parse fails: return { valid: false, error: "parse_error" }.
5. If parse succeeds but result is not an object: return { valid: false, error: "not_object" }.
6. For each key in required_keys:
- If key missing: return { valid: false, error: "missing_key: {key}" }.
7. Return { valid: true, data: parsed }.
Retry protocol: On validation failure, make ONE retry call with this prompt structure:
Your previous output was not valid JSON.
Error: {error_description}
First 500 characters of your output: {truncated_output}
Return ONLY a valid JSON object with these required keys: {required_keys}.
No markdown code fences. No explanatory text. Just the JSON.
If the retry also fails, use the fallback behavior described in the specific command step.
Context Window Management
Rounds accumulate data fast. Without truncation, later rounds get degraded output or hit context limits.
For the round simulation prompt (step 4c):
| Round Being Simulated | What to Include |
|---|---|
| 1 | Persona summaries only (no prior actions) |
| 2-3 | Full actions from all prior rounds |
| 4+ | Full actions from rounds N-1 and N-2. For rounds 1 through N-3, include ONLY the summary headline + key_events from summaries.json. Truncate any individual action content field to 300 chars when referenced in historical context. |
For the round summary prompt (step 4h):
- Always include: full actions from the current round.
- Include: previous round's summary (not full actions).
For the memory updater prompt (step 4i):
- Include: full actions from the current round only.
- Include: current entity and relationship lists from graph files.
Key Implementation Notes
- All templates:
${CLAUDE_PLUGIN_ROOT}/templates/ - All scripts:
${CLAUDE_PLUGIN_ROOT}/scripts/ - User data:
.swarmfish/in project root - Model mapping:
"opus"maps to Agentmodel: "opus", same for sonnet/haiku - Actions log:
actions.jsonl(one JSON object per line, append-only) - Summaries:
summaries.json(JSON array, read-append-write each round) - Memory updates:
graph/memory-updates.json(JSON array, read-append-write each round) - Sim ID format:
sim-{YYYYMMDD}-{4-char-hex}(e.g.,sim-20260414-e9b2)