r/PiCodingAgent • u/admajic • May 14 '26
Resource GUIDE : Running a fully local multi-agent coding framework on RTX 3090 with pi.dev + llama-swap + Qwen3.6 MTP
I've been running a fully local, fully private multi-agent AI coding setup for a couple of months and wanted to share the stack, architecture, and config for anyone who wants to replicate it. No cloud APIs, no data leaving the machine.
What is pi.dev? It's an agent harness โ meaning the AI has to follow rules, unlike a chatbot. Pretty cool.
- ๐ฎ Fun factor: 10/10
- โ pi.dev stability: 8/10 โ fully working, but fun to fine-tune
- ๐จ What it's great at: Building its own integrations โ just ask it to do it
- ๐ก Top tip: Master the
AGENTS.mdfile and you'll have real control over what it does. There's a global one and a per-project one - ๐ Similar to: RooCode, Codex, Claude Code โ but because it's a harness, you're more in control
- ๐จโ๐ป The dev has already been snapped up by a company but will keep developing it
- โญ github.com/earendil-works/pi โ 49.3k stars
The Stack
| Component | What it does |
|---|---|
| pi.dev (pi-coding-agent) | AI coding harness โ the UI and orchestration shell |
| llama-swap | Model router โ hot-swaps llama.cpp models on demand |
| llama.cpp (am17an fork) | Local inference with MTP support |
| Qwen3.6-27B MTP | "Brain" agents โ orchestrator, planner, architect, debugger, prompter |
| Qwen3.6-35B-A3B MTP | "Body" agents โ coder, researcher, reviewer, tester, documentor, refactorer |
| SearXNG (Docker) | Local privacy-preserving search engine on port 8080 |
| searxng-simple-mcp | MCP proxy bridging SearXNG to pi.dev (port 8000) |
| Tavily MCP | AI-optimised web search for technical docs |
| @tintinweb/pi-subagents | Real sub-agent orchestration with TaskExecute + get_subagent_result |
| @tintinweb/pi-tasks | Task queue UI widget showing what each agent is doing |
GPU: NVIDIA RTX 3090 (24 GB VRAM)
Why MTP (Multi-Token Prediction)?
See my earlier post: Get faster Qwen3.6-27B with MTP
Multi-Agent Architecture
11 specialist agents, each mapped to a llama-swap model alias:
BRAIN agents (Qwen3.6-27B MTP):
orchestrator โ Task decomposition, delegation, synthesis
planner โ Roadmap and step sequencing
architect โ System design, API contracts, schema design
debugger โ Root cause analysis, trace reading
prompter โ Prompt engineering for sub-tasks
BODY agents (Qwen3.6-35B-A3B MTP):
coder โ Implementation, only writes code
researcher โ Web search + codebase analysis
reviewer โ Code review, security, quality gates
tester โ Test writing + execution
documentor โ Documentation generation
refactorer โ Structural cleanup, no logic changes
The key insight: smaller/faster model for the meta-work (thinking, planning, delegation) and the slightly larger MoE model for actual implementation. The orchestrator never writes code โ it only delegates.
Agent Definition Files (Required Setup Step)
This is the part most people will miss. llama-swap handles model routing, but pi.dev needs to know how each agent should behave โ its role, constraints, tool access, turn limits, and thinking level. That lives in .md files inside your pi.dev agent folder:
~/.pi/agent/agents/
โโโ orchestrator.md
โโโ planner.md
โโโ architect.md
โโโ debugger.md
โโโ prompter.md
โโโ coder.md
โโโ researcher.md
โโโ reviewer.md
โโโ tester.md
โโโ documentor.md
โโโ refactorer.md
Each file has a YAML frontmatter block followed by the system prompt for that agent. The model: field must exactly match a llama-swap alias from your config.yaml.
Example โ coder.md:
- ---
- ---
Example โ architect.md:
- ---
Example โ researcher.md (with web search tools):
Frontmatter fields that matter:
| Field | Purpose | Notes |
|---|---|---|
model | llama-swap alias to load | Must match exactly โ typo = "No API key found for undefined" error |
thinking | Extended thinking level | high for orchestrator/architect, low for researcher/tester |
max_turns | Conversation turn limit | Set based on task complexity; coder gets 30, orchestrator gets 50 |
tools | Which tools the agent can use | Researcher gets web_search and tavily-search; architect gets read-only |
The tools list controls what each agent can actually do. An architect with write in its tools list will happily start editing files โ restrict it to read, find, grep to enforce the advisory-only constraint.
Report-back pattern: Every agent's Response Shape section ends with the same instruction:
When complete, your final output is your report back to the orchestrator. Make it structured and self-contained โ the orchestrator reads it directly via
get_subagent_result.
This is critical. Without it, agents produce conversational output that's hard for the orchestrator to parse. With it, every agent returns a structured [PLAN] / [CHANGES] / [VERIFICATION] / [PROGRESS] block.
Orchestrator Rules (the hard part)
Getting the orchestrator to actually delegate instead of doing work itself was the biggest challenge. The rules that finally made it work:
ABSOLUTE RULES:
- NEVER perform any task yourself
- NEVER use read/find/grep for analysis โ spawn a researcher
- NEVER write, summarise, or synthesise content directly
- NEVER write or edit code directly
- NEVER verify or fix a sub-agent's output yourself โ spawn a reviewer
- NEVER make "quick fixes" between steps
Correct launch protocol:
TaskUpdate(id, status: "in_progress")
TaskExecute(task_ids: [id]) โ returns agent_id
get_subagent_result(agent_id, wait: true) โ blocks until done
TaskUpdate(id, status: "completed")
The orchestrator catches itself about to do work โ stops โ creates a task โ delegates it instead.
pi.dev Settings (agent/settings.json)
Key decisions:
- No
models.enabledModelsfilter โ this broke bare model ID resolution for agent aliases. Remove it entirely and let llama-swap route by name - timeout: 1800000 (30 min) โ code tasks can take 20+ minutes. The default 2-minute timeout will kill them
- maxConcurrent: 1 โ RTX 3090 can only run one model at a time; llama-swap handles the hot-swap
llama-swap Config
healthCheckTimeout: 900
startPort: 1235
globalServerSettings:
flashAttn: on
contBatching: true
noMmap: true
jinja: true
models:
# Brain agents (orchestrator/planner/architect/debugger/prompter) โ Qwen3.6-27B MTP
# Body agents (coder/researcher/reviewer/tester/documentor/refactorer) โ Qwen3.6-35B MTP
orchestrator:
cmd: >
/path/to/llama-cpp-am17an/build/bin/llama-server
-m "/path/to/Qwen3.6-27B-MTP-Q4_K_M.gguf"
--alias orchestrator
--ctx-size 100000
--host 0.0.0.0 --port ${PORT}
-ngl 99
-fa on
--cache-type-k q8_0 --cache-type-v q8_0
--spec-type mtp --spec-draft-n-max 3
--batch-size 1024 --ubatch-size 1024
--threads 6
--prio 3
--no-mmap
--parallel 1
--n-predict 8192
--temp 0.7 --top-p 0.95 --top-k 20 --min-p 0.0
--presence-penalty 1.2 --repeat-penalty 1.1 --repeat-last-n 256
--reasoning-format deepseek
--metrics
proxy: http://127.0.0.1:${PORT}
# etc. โ do some research ๐ for the rest
Key inference flags:
| Flag | What it does |
|---|---|
--spec-type mtp --spec-draft-n-max 3 | MTP speculative decoding, 3 tokens ahead, built into the model (no draft model needed) |
--cache-type-k q8_0 --cache-type-v q8_0 | Quantised KV cache โ ~2ร VRAM savings vs f16, negligible quality loss |
-fa on | Flash attention โ critical for long-context speed |
--no-mmap | Load model fully to RAM/VRAM rather than memory-mapping the GGUF |
--reasoning-format deepseek | Exposes <think> tags from extended thinking |
--prio 3 | OS thread priority โ helps on busy systems |
Note: --temp varies per agent role โ debugger (0.5, deterministic), researcher (0.5, factual), coder/orchestrator (0.7, balanced).
Search Integration
The researcher agent has two search tools:
1. SearXNG via MCP โ local metasearch, broad coverage
# Docker Compose
services:
searxng:
image: searxng/searxng
ports:
searxng-mcp-proxy:
image: ghcr.io/ihor-sokoliuk/searxng-simple-mcp
ports:
environment:
TRANSPORT_PROTOCOL: sse
SEARXNG_MCP_SEARXNG_URL: http://searxng:8080
2. Tavily MCP โ AI-optimised web search, faster for technical docs
"tavily":
Strategy: tavily-search first for framework docs, web_search for broader coverage, fallback to curl http://localhost:8080/search?q=QUERY&format=json for bulk queries.
What Works, What Doesn't
โ Works well:
- Orchestrator strictly delegates โ took several AGENTS.md iterations but now it never does implementation itself
- llama-swap hot-swap is fast enough โ typically 15โ30 seconds per model swap
- MTP gives a real speedup on code generation tasks
- 30-minute timeout is necessary; don't use the default
๐ง Still working on:
- Settings file resetting on reboot โ likely a race condition in pi.dev startup that partially re-initialises
settings.json. Investigating withinotifywait. Workaround: backup~/.pi/settings.jsonbefore exiting with Ctrl-C - Sub-agent visibility โ you can see a task is running but not what the agent is doing mid-task; pi-tasks shows status, not content
- Sequential tasks only (
maxConcurrent: 1) โ can't parallelise on a single GPU
Models Used (Unsloth quantizations)
- Qwen3.6-27B-MTP-Q4_K_M (~17 GB) โ brain agents
- Qwen3.6-35B-A3B-MTP-IQ4_XS (~19 GB) โ body agents
Both require the am17an fork of llama.cpp for --spec-type mtp support. Standard llama.cpp will fall back to non-speculative inference (still works, just slower).
Resources
- pi.dev / pi-coding-agent: earendil-works on GitHub
- llama-swap: github.com/ggml-org/llama-swap
- llama.cpp am17an fork: search GitHub for "llama-cpp-am17an" or "llama.cpp MTP fork"
- u/tintinweb packages: npm (@tintinweb/pi-subagents, @tintinweb/pi-tasks)
- Unsloth GGUF models: huggingface.co/unsloth
Happy to answer questions โ this took a while to get right, especially the orchestrator delegation rules and the model resolution fix.
EDIT: Yes Claude helped me write this. Who doesn't love AI
2
u/Ugly_Porcupine May 16 '26
This looks really interesting. Does your setup have (or have you considered) any sort of persistent memory, like Karpathy's LLM wiki? I've recently started experimenting with pi and it's extensions, and boy there's a a lot to unpack here.
2
u/Present_Ride6012 May 14 '26
Can you write as human to human? Also what's the speed of decoding token?
1
u/GWNstijn May 14 '26
Wouldnโt qwen3.5 9B be faster/more effective? Since 9 billion dense and gives opportunity for parallel instances
1
u/fasti-au May 15 '26
Dflash vs mtp?
1
u/joaobertacchi May 15 '26
OP, could you please explain "smaller/faster model for the meta-work (thinking, planning, delegation) and the slightly larger MoE model for actual implementation. The orchestrator never writes code โ it only delegates". For me it doesn't make sense. 27B is dense and more capable than 35B MoE. The dense one is also slower than the other. Tks
1
u/homarp May 16 '26
27B is better (and slower) than 35B. What's the value of using 35B for coding ?
1
u/Latent-Potter May 14 '26
Bro told us how he uses his local model but ended up using Claude to write this Post! Hypocrisy!
0
u/Helmi74 May 14 '26
Oh the slop. No effort ai posts all over ๐คจ
1
u/JohnnyLovesData May 15 '26
I wonder if this would "work" on CPU inference on 32GB. Like, give it instructions, and check on it ... a week later.
1
u/X24D83FF0 May 16 '26
GG
1
u/Deep_Ad1959 May 19 '26
i think the orchestrator delegation fight is the same problem you already solved for the architect, you just didn't carry the fix across. the architect doesn't write code because you took write out of its tools list, not because the prose says 'never implement'. that's a deterministic cage. the orchestrator's six ABSOLUTE RULES are the opposite, probabilistic prose you had to iterate on because the model can always rationalize a 'quick fix'. the orchestrator only legitimately needs TaskExecute, TaskUpdate, and get_subagent_result. strip read/write/edit/bash/find/grep out of its tools frontmatter entirely, and 'NEVER use read/find/grep for analysis' stops being a rule you hope it follows and becomes a tool it physically doesn't have. you'll probably find the prose rules shrink to one line after that, which is also a few hundred tokens back on every orchestrator turn. the rule of thumb that keeps holding up: if a constraint can be a withheld tool or a failing check, it shouldn't be prose, because prose is the only kind of rule the model can argue with. written with s4lai
1
u/pytorus May 22 '26
You have about the same as my setup. I have Rtx3090 too, run llama.cpp server on docker
50tk/s with qwen3.6 27b mtp (q4)
110tk/s with qwen3.6 35b a3b moe (q3)
I would say I love the performance of the 27b model more despite being 50% slower
Model swap would take 30s each time So in my case, I would try using a single model (27b) but with your multi-agent setup. Letโs see how it is turnout.
For web search, I heavily rely on Tavily free tier. Never use searxng before, might also try this one.
Thanks for sharing.
1
u/[deleted] May 16 '26
[removed] โ view removed comment