Skip to content

Claude Code: skill.md Step 3B silently fails with read-only subagents (Explore type) #195

Description

@Axelcureno

Summary

When running /graphify in Claude Code, the semantic extraction step (Step 3B) silently fails for a majority of chunks when the coordinator dispatches to the Explore subagent type. The skill template's wording does not specify an agent type, so the model can pick Explore for parallel dispatch — which is read-only and cannot write the chunk output files the coordinator expects.

Environment

  • graphifyy 0.4.0 (installed via pipx install --python python3.13 graphifyy)
  • Claude Code (Opus 4.6, 1M context)
  • Skill installed via graphify install~/.claude/skills/graphify/SKILL.md
  • macOS 14, Python 3.13.12

What happened

Dispatched 12 parallel subagents in one message for a ~470k-word corpus (mas codebase, 674 files). Used Agent(subagent_type="Explore", ...) because Explore is the recommended type for "exploring/reading" work in Claude Code.

Result: only 5 of 12 chunks actually wrote graphify-out/.graphify_chunk_NN.json to disk. The other 7 agents responded with inline JSON in their text output, a mix of:

  • JSON in a fenced code block followed by the words "chunk N written" (coordinator has to parse this back out)
  • JSON with extra commentary before/after ("Here's the extraction: …")
  • Narrative analysis with no JSON at all (one of the image chunks literally responded: "I cannot create the output file as I'm in read-only mode.")
  • A heredoc (cat > ... << EOF) that never executed because Explore has no Bash tool

I had to salvage 5 chunks from agent response text, and hand-reconstruct 2 image chunks from narrative descriptions.

A subsequent re-run on the same corpus with subagent_type="general-purpose" (which has Write/Bash access) completed all 12 chunks cleanly:

Metric First run (Explore) Re-run (general-purpose) Delta
Semantic nodes 198 469 2.4×
Semantic edges 155 542 3.5×
Hyperedges 11 27 2.5×
Chunks wrote to disk 5 / 12 12 / 12

The first run silently under-counted by more than half. A user who didn't spot-check .graphify_chunk_*.json on disk would never know.

Why the skill template is susceptible

Relevant excerpt from Step B2 in graphify/skill.md:

Step B2 — Dispatch ALL subagents in a single message

Call the Agent tool multiple times IN THE SAME RESPONSE — one call per chunk. …
Each subagent receives this exact prompt … Output exactly this JSON (no other text):

The prompt tells the subagent to "output exactly this JSON" but does not instruct the coordinator on:

  1. Which subagent type to use. On Claude Code, general-purpose has Write/Bash; Explore does not. The skill picks whichever type the model thinks fits the verb "extract", and "extract" sounds read-only.
  2. Whether the subagent should write the JSON to a file or return it inline. The skill template is ambiguous — the per-subagent prompt says "output exactly this JSON" (sounds inline) but the coordinator's Step B3 reads from per-chunk files (.graphify_chunk_NN.json), implying disk.
  3. How the coordinator should distinguish "agent returned JSON inline" from "agent wrote to disk" when merging. Currently: it doesn't. If the file is missing, the chunk is lost silently.

In my case the model picked Explore based on surface-level read-only semantics ("you are reading files and extracting"), and silently lost 7 chunks.

Suggested fix (small, skill.md only)

Two changes to Step B2:

1. In the coordinator dispatch instructions, specify the subagent type explicitly:

Claude Code users: use subagent_type="general-purpose" when dispatching. Do NOT use Explore — it is read-only and cannot write the chunk files. On Codex, use the default agent. On other platforms, use whichever subagent type has Write/Bash access.

2. In the per-subagent prompt, change the output instruction from "Output exactly this JSON" to:

Use the Write tool to save the JSON to graphify-out/.graphify_chunk_NN.json. Do NOT print the JSON in your response. Reply only with "chunk NN written" so the coordinator can merge.

Then in Step B3, the merge logic is already correct (it reads per-chunk files from disk) — it just needs to warn when a chunk file is missing rather than silently skipping.

This makes the pipeline robust to agent-response format drift and gives the coordinator a single reliable signal: file exists on disk = success.

Related

  • Issue collect_files() in extract.py ignores .graphifyignore #188 ("collect_files() in extract.py ignores .graphifyignore") — I hit this too; .graphifyignore worked at the top level but deeper **/coverage/ patterns required explicit paths. Separate from this bug, but worth cross-referencing if you're touching file enumeration.

Workaround for users on Claude Code today

If you're running /graphify in Claude Code today, explicitly tell Claude at the start of the invocation: "use subagent_type='general-purpose' for the graphify extraction dispatch". Claude will honor it, and you'll get full semantic extraction on the first try.


Happy to open a PR for the skill.md fix if it'd be useful — it's a ~4-line change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions