Multi-Repo Agentic Workflows: Guardrails, Fast Classifiers, and the Sub-50ms Boundary
How a Cross-Project Lean Sprint Unified Neural Intent Classification with Deterministic CLI Performance
Who this is for — system architects, CLI designers, and AI engineers orchestrating autonomous multi-agent pipelines across multiple decoupled repositories.
Read this if — you want to bridge natural language intent into strict CLI interfaces without sacrificing millisecond-level responsiveness, or you manage multi-agent development workflows across repository boundaries.
Skip this if — you only write standalone single-repo scripts with no performance constraints.Takeaways
- The Sub-50ms Boundary is Absolute: Synchronous keystroke and shell tab-completion paths must remain 100% deterministic (<5 ms); model inference (~200–500 ms) belongs strictly at command invocation time.
- GBNF Grammar Constraints Eliminate Hallucination: Constraining local model decoders with BNF grammars guarantees 100% schema validity, ensuring an agent or user argument maps strictly to a declared enum or explicitly abstains.
- The Zero-Coding Host Reviewer Pattern: When a host orchestrator restricts itself to read-only diff inspection and delegates all file edits to low-cost worker agents, context bloat disappears and token velocity quadruples.
- Plan-First Read-Only Gating Catches Protocol Bugs Early: Forcing subagents to output a concrete file and test plan before granting write access catches missing flags, schema collisions, and test omissions before dirtying the working tree.
- Clean Multi-Repo Separation Requires Stable CLI Contracts: Separate tools (
harnez,neus,lmcoder) should communicate over bounded JSON CLI contracts rather than internal library imports or shared memory.
1. The Architectural Dilemma: Natural Intent vs. CLI Rigor
As agentic developer tools evolve, a fundamental ergonomic tension emerges:
- Strict Command-Line Interfaces demand precise flags, canonical enums, and exact syntax (
harnez agent start --role developer). - Autonomous Agents & Human Users express intent in fuzzy, natural language (
harnez agent start --role "review the PR diff"orharnez agent start explorer "audit the SQL queries").
When an agent guesses a near-miss argument (such as --role explorer instead of --role advisor), conventional CLIs fail abruptly with unknown role "explorer". In a long multi-agent workflow, these tiny syntax collisions cause failed turns, retry loops, and human frustration.
The naive solution is tempting: “Why not put an LLM in the shell’s auto-complete function or argument parser to dynamically classify every keystroke?”
In this case study, we walk through the empirical research, the performance constraints that shattered this naive approach, and the robust multi-repo architecture built to solve it.
2. The Empirical Reality: The Sub-50ms Boundary
Before writing code, we dispatched parallel research agents across three repositories:
neus: A Go-based neural search and AST-indexing engine.lmcoder: A local model lifecycle manager servingllama.cppinstances (127.0.0.1:8736fast chat,:8734primary chat,:8746embeddings).harnez: The multi-agent harness and developer CLI.
The research subagents benchmarked local small models (Qwen2.5-0.5B and Qwen2.5-1.5B) executing GBNF-constrained enum classification on local AMD APU hardware:
| Model / Strategy | Latency (p50 / p95) | Cold Start | Schema Validity | Exact Match Rate |
|---|---|---|---|---|
| Qwen2.5-0.5B (GBNF Enum) | 176 ms / 279 ms | 703 ms | 100% | 34.8% (95.7% safe outcome) |
| Qwen2.5-1.5B (GBNF Enum) | 285 ms / 410 ms | 1.52 s | 100% | 56.5% (82.6% safe outcome) |
| Multi-field Extraction | 1.45 s / 2.10 s | — | 100% | 70.0% |
flowchart LR
subgraph Budget["Human Keystroke Budget (<50 ms)"]
K[Keystroke / Tab] --> Fast[Cobra Offline Prefix Match < 2 ms]
Fast --> OK[Instant Shell Completion]
end
subgraph Neural["Neural Model Inference (176 - 285 ms)"]
K2[Keystroke / Tab] --> LLM[Local Fast LLM :8736]
LLM -.-> Lag["Severe Terminal Lag & Stutter (Unacceptable)"]
end
The Architectural Takeaway
Synchronous shell completion must never depend on neural inference.
Interactive tab-completion must remain strictly deterministic, instant (<5 ms), and offline. Neural classification belongs exclusively at command invocation time—resolving natural language after the user presses Enter.
3. The Multi-Repo Assembly Line: Step-by-Step Architecture
To implement this vision without coupling codebases, we established a strict contract boundary across neus and harnez.
flowchart TD
subgraph CLI_Invocation["User / Subagent Command Invocation"]
CMD["harnez agent start 'review the commit diff'"]
end
subgraph Step1["Step 1: Harnez Argument Cascade"]
CMD --> CheckExact{"1. Exact Match in spec/agent.yaml?"}
CheckExact -->|Yes| Direct["Direct Role (developer, reviewer...)"]
CheckExact -->|No| CheckAlias{"2. Static Alias Match?"}
CheckAlias -->|Yes (e.g. explorer -> advisor)| AliasRole["Resolved Canonical Role"]
CheckAlias -->|No| CheckOmitted{"3. Role omitted entirely?"}
CheckOmitted -->|Yes| PromptInfer["Extract prompt summary"]
CheckOmitted -->|No| RawArg["Use raw unknown argument"]
end
subgraph Step2["Step 2: External Neus Classify Contract"]
PromptInfer --> NeusCLI["neus classify --json --classes orchestrator,developer,reviewer,advisor '<input>'"]
RawArg --> NeusCLI
NeusCLI --> FastLMCoder["lmcoder Resident Service (127.0.0.1:8736)"]
FastLMCoder --> GBNF["GBNF Grammar Constraint (+ unknown abstention token)"]
end
subgraph Step3["Step 3: Policy Enforcement"]
GBNF --> Result{"Result Class"}
Result -->|Canonical Role| SpawnCheck["CheckSpawn Policy & Permission Verification"]
Result -->|Abstain / Timeout / Error| Fallback["Show Known Roles & Aliases Catalog"]
SpawnCheck --> SessionLaunch["Start Isolated Subagent Session"]
end
1. neus classify: A Stable, Bounded Interface
Instead of importing internal Go packages across repo boundaries, neus exposes a clean CLI command:
neus classify --json --classes orchestrator,developer,reviewer,advisor "audit SQLite performance"
Output:
{
"class": "advisor",
"input": "audit SQLite performance",
"classes": ["orchestrator", "developer", "reviewer", "advisor"],
"model": "",
"latency_ms": 536,
"source": "model"
}
If the input is an exact or unique prefix match (e.g. "review"), it short-circuits in <1 ms with "source": "prefix". If the model is uncertain, it selects the private unknown grammar token and exits with code 2 (abstention).
2. harnez: The Dynamic Resolver Cascade
When harnez agent start is called:
- Exact match: Checks canonical roles defined in
spec/agent.yaml. - Static aliases: Checks rich aliases (e.g.
coder$\rightarrow$developer,explorer$\rightarrow$advisor). - Prompt Auto-Inference: When
--roleis omitted, the prompt is sent toneus classifywith a 1.5s bounded timeout. If classified asrevieweroradvisor, Harnez prints an advisory notice and sets the role, falling back safely todeveloper. - Positional Ergonomics:
harnez agent start explorer "audit queries"automatically extracts the leading role token without requiring--role.
4. The Agentic Sprint in Action: Guardrails & Review Discipline
The implementation was delivered using the Lean Fresh-Handoff Sprint workflow. The Host Orchestrator operated under strict invariants:
Invariant 1: Zero Coding by the Orchestrator
The host never edited Go source files, YAML configs, or test fixtures. All changes were authored by dispatched codex:luna:med developer subagents. This kept the orchestrator’s context window pristine and dedicated entirely to diff review.
Invariant 2: Plan-First Read-Only Gating
Every developer worker was first launched in read-only mode ("read-only: plan ticket XXX..."). The orchestrator reviewed the plan (schema fields, test cases, error paths) before issuing a resume command with write authority.
[Host] harnez agent start --role developer --model codex:luna:med "read-only: plan ticket 686..."
[Worker] Emits concrete plan: files, GBNF enum handling, test mock strategy.
[Host] Reviews plan -> "Plan approved; implement milestone M1 now..."
[Worker] Implements, runs tests, commits, and reports back.
Invariant 3: Quota-1 Test Budget
Workers were bounded to a single full test suite run (make test-q1) before committing. When tests failed, the worker had to inspect the captured failure log, correct the root cause, and re-verify once rather than thrashing in an infinite loop.
5. Honest Post-Mortem: Real Bugs Caught in the Loop
No engineering system is built without friction. Here are the candid failures encountered and resolved during this session:
graph TD
subgraph Bug1["Bug 1: Test Server Goroutine Hang"]
B1[Worker writes HTTP timeout test] --> H1[httptest.Server handler blocks indefinitely]
H1 --> TO[Go test hits 10-minute timeout]
TO --> F1[Fix: Bound handler wait with context cancellation]
end
subgraph Bug2["Bug 2: Abstention Token Assertion Inversion"]
B2[Worker adds 'unknown' to GBNF grammar] --> A2[Test asserts JSON classes omits 'unknown']
A2 --> TF[Test fails on class list mismatch]
TF --> F2[Fix: Align test assertions with abstention schema]
end
subgraph Bug3["Bug 3: Test Environment Pollution"]
B3[Live prompt inference added to CLI] --> T3[Legacy CLI tests fail expecting static stderr]
T3 --> F3[Fix: Inject deterministic abstaining classifier in unit tests]
end
- The Goroutine Server Hang: A simulated network timeout test spawned an HTTP test server that waited indefinitely, triggering Go’s 10-minute test timeout. The worker diagnosed the stuck channel, bounded the handler to 1s, and re-verified cleanly.
- Abstention Assertion Inversion: The developer added
unknownas a private grammar token for model refusals, but wrote tests asserting that the public class list excludedunknown. Reviewing the diff during milestone inspection caught the failure immediately. - Legacy Test Pollution: Adding prompt auto-inference caused existing unit tests to capture classifier logs on
stderr. Injecting a mock classifier during test suite execution isolated the tests from ambient host model state.
6. The Result: Unified, Observable Ergonomics
By the end of the sprint, the entire subagent workflow was verified live:
# 1. Starting an agent with natural language prompt (inferred role: advisor)
$ harnez agent start "audit the sqlite indexing queries in neus"
harnez: inferred role "advisor" (aliases: explorer, planner) from prompt
[session info: id=01a103... name=codex-01a103 role=advisor]
# 2. Positional role shorthand
$ harnez agent start review "check diff on HEAD~1"
[session info: id=01a104... name=codex-01a104 role=reviewer]
# 3. Fuzzy substring session resumption
$ harnez agent resume classify "run the CLI tests again"
harnez: matched session "neus-classify-dev" (id: 01a10277-43c9...)
[resuming session neus-classify-dev...]
# 4. Contextual directory resumption
$ cd /home/uwe/projects/neus && harnez agent resume "continue with M2"
harnez: resuming latest active session "neus-classify-dev" (last active 2m ago)
7. Rules for the Multi-Repo Fleet
- The Performance Fence: Any operation running on a keystroke or shell tab-completion hook must complete in under 5 ms. Never invoke neural models or external network sockets synchronously.
- The Grammar Guard: When interfacing natural language with code execution, never parse raw unstructured LLM text. Constrain outputs with GBNF or JSON Schemas, and always provide an explicit
unknownabstention path. - The Orchestrator’s Fence: Keep host orchestrators out of the code editor. Review diffs, run verification targets, update tickets, and delegate implementation to low-cost, disposable subagents.