Cache the claude backend system prompt via Anthropic prompt caching
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- python
- Domain
- ai, performance
Research direction
Start in graphify/llm.py at _call_claude() and review how the Anthropic SDK accepts system content blocks with cache_control. Apply caching to the extraction system prompt as described, then verify the call still uses the same prompt and message content. The issue defines done as enabling prompt caching for the native Claude backend without changing output.
Written by the indexing model from the issue text.
Description
Summary
extract --backend claude issues one messages.create call per file, and each call re-sends the fixed _extraction_system prompt at full input price. Marking the system block with Anthropic prompt caching (cache_control: ephemeral) bills that shared prefix at ~0.1× on reads after the first call. Output is unchanged — this is a billing/latency optimization only.
Where
graphify/llm.py, _call_claude() — system= is passed as a plain string, so the extraction system prompt is re-ingested on every per-file call.
Proposed change
diff
resp = client.messages.create(
model=model,
max_tokens=max_tokens,
-
system=_extraction_system(deep=deep_mode),
-
system=[{ -
"type": "text", -
"text": _extraction_system(deep=deep_mode), -
"cache_control": {"type": "ephemeral"}, -
)}], messages=[{"role": "user", "content": _anthropic_content(user_message, images or [])}],
The anthropic SDK already in use supports the content-block form of system with cache_control.
Why it helps
_extraction_system is identical across all per-file calls (only deep toggles). On a repo with N files the system prefix is paid N× at 1×; with caching it’s one write (1.25×) + (N−1) reads (0.1×) → ~90% off the system portion of input.
Caveats (for reviewers)
Only the system block is cacheable here; per-file user content isn’t reused.
Needs the system prompt ≥ the model’s min cacheable length (e.g. 512 tokens on recent Sonnet/Opus); below that it silently no-ops (cache_*_input_tokens = 0), no error.
With --max-concurrency > 1 the first wave of parallel calls misses (a cache entry is only available after the first response begins) — still a net win on multi-file runs.
5-min ephemeral TTL refreshes on each hit, so it stays warm through an active extraction.
Scoped to the native claude backend; the Bedrock path (system=[{"text": ...}]) uses a different caching mechanism and could be a follow-up.
Impact
Billing/latency only. No behavior change.
- Dominant language
- Python
- Stars
- 124k
- Forks
- 11.9k
- Avg merge
- 2h 35m
- Merged PRs (30d)
- 6
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Graphify-Labs/graphify
-
`file_hash` opens the lowercased path on Windows, so files with uppercase names fail on case-sensitive dirs (`\wsl.localhost`)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Graphify-Labs/graphify#4925 · 1 comment ·
Maintainers usually reply within 1 day
-
watch liveness check resolves relative source identities against process CWD instead of watch rootPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Graphify-Labs/graphify#4896 · 5 comments ·
Maintainers usually reply within 1 day
-
extract --out <dir>: semantic cache never saved, docs missing from manifest (relative source_file resolved against --out)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Graphify-Labs/graphify#4831 · 3 comments ·
Maintainers usually reply within 1 day
-
hooks: last-resort `python3` probe launches the Microsoft Store redirector on Windows (visible console flash, exit 9009)Possibly taken @Deepjyoti-Sarmah claimed this 14 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Graphify-Labs/graphify#4563 · 2 comments ·
Maintainers usually reply within 1 day
-
GRAPHIFY_DISABLE_THINKING is ignored by the claude backend, so thinking eats max_tokens and extraction truncatesPossibly taken @bercedev claimed this 14 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 69/100
Graphify-Labs/graphify#4546 · 1 comment ·
Maintainers usually reply within 1 day
All issues in Graphify-Labs/graphify
Similar issues
-
area:scripts area:tests bug priority:later
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Ikalus1988/MisakaNet#4358 ·
Maintainers usually reply within 1 day
-
Discovered ports from service discovery are never propagated to modules in Module.load()Possibly taken @vishalmore90 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OWASP/Nettacker#1828 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
aws-samples/sample-per-model-bedrock#708 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
sjkim1127/Reversecore_MCP#365 ·
Maintainers usually reply within 1 day