The Volks

What a volk is

A volk is a single specialist agent inside Orchestrata's multi-agent software-delivery system. The name is deliberate: no volk is a generalist. Each one owns exactly one job — clarifying an intent, writing user stories, drawing an architecture, generating code, running tests — and each carries a strong role persona that keeps it inside its lane. What turns eleven narrow specialists into a team rather than eleven disconnected prompts is a shared contract, and that contract lives in code.

Every volk subclasses BaseAgent (agents/volks/base.py), a Pydantic model that gives each one an identity (id, alias, role), a live status (WorkStatus), and — most importantly — a mouth and ears. Volks do not call each other directly; they speak in CXP packets routed through a shared Postman (send() / emit_event()), and they observe one another through an async event mesh (self.events). When a volk needs something another volk owns — a clarified requirement, a design decision, a test result — it consults that peer by alias using the message_volk tool rather than guessing. That rule, and the framing that makes the volks a coherent crew, is injected into every volk's system prompt by compose_persona() (agents/volks/persona.py), which prepends a shared VOLK_TEAM_PREAMBLE in front of each role prompt so the team contract stays DRY instead of being re-implied in ten separate strings.

The result is an assembly line. A human's vague intent enters at one end, and each volk in turn refines it, hands its structured output to the next volk over CXP, and the orchestrator watches the whole convoy's status the entire time. The sections below walk that line volk by volk.

Shared foundation — BaseAgent

Every volk inherits the same machinery. BaseAgent provides set_postman() / set_kg() wiring, the CXP send()/emit_event()/process() contract, an event-mesh node (events), best-effort memory recall folded into every LLM call (_recall_block, SPEC-010), and three brain-call helpers: _call_llm (chat), _call_reasoner (deep reasoning), and _call_llm_with_tools (a multi-turn tool loop that lets a volk read files, search code, and run shell commands before answering). Because all brain calls flow through these helpers, a test can inject a fake _call_llm and the whole volk runs offline.

Diagram projects-orchestrata-ultimate-volks-1

Which brain each volk uses

There is no hardcoded model anywhere in the volks. Which provider/model each volk talks to is resolved by alias from a profile file — configs/spike-profiles.yaml — selected by the SPIKE_PROFILE env var (default default). One YAML is the single source of truth, and swapping the profile re-brains the whole team at once. The default profile runs everyone on DeepSeek (v4-pro for the reasoning-heavy roles, v4-flash for the lighter ones); the claude profile maps the same aliases onto Haiku/Sonnet/Opus; kimi, qwen, budget (local Ollama), and mix offer other fleets. The table below reads the two most-used profiles:

Volk Alias default (DeepSeek) claude
Concierge U:Cx deepseek-v4-pro haiku
Analyst U:BA deepseek-v4-pro sonnet
Project Manager U:PM deepseek-v4-pro sonnet
UX Designer U:Ux deepseek-v4-flash sonnet
Architect U:Ar deepseek-v4-pro opus
CodeDirector U:Cd deepseek-v4-pro sonnet
Junior J:Junior deepseek-v4-flash sonnet
QA U:Qa deepseek-v4-pro sonnet
Compliance U:Cp deepseek-v4-flash sonnet
Senior Dev U:SD deepseek-v4-pro opus
Documentor U:Do deepseek-v4-flash sonnet

Compliance is the one exception that never spends a token: ComplianceVolk is deterministic (no LLM calls at all) — its profile entry only exists as a formality. The heaviest thinkers (Architect and Senior Dev) get the top tier in every profile.

The pipeline

The volks form a delivery pipeline. Intent flows down the CXP line; each arrow below is a real CXP subject and each volk's escalation_target names who it hands to next.

Diagram projects-orchestrata-ultimate-volks-2

The eleven volks in detail

Concierge — U:Cx (concierge/volk.py, ConciergeVolk)

The Concierge is the front door. Its job is to take a vague human intent and turn it into a precise, testable, implementation-ready requirements spec that an architect can act on without ambiguity. Its CONCIERGE_SYSTEM_PROMPT frames it as a senior business analyst and requirements engineer, and it works a disciplined loop: on the first response it must always ask 3–6 clarifying questions (never jump straight to "complete"), running a structured gap analysis across seven dimensions — functional scope, technology stack, data model, interfaces, quality attributes, deployment (default Incus, never assume Docker), and constraints. Questions are forced-choice ("do you need X or Y?") to disambiguate rather than educate.

Analyst — U:BA (analyst/agent.py, AnalystAgent)

The Business Analyst receives the Concierge's cleaned-up request and turns it into a formal, numbered specification. Its ANALYST_SYSTEM_PROMPT (SPEC-019) makes it classify the project type (library, CLI, web API, desktop, refactor), pin the technology decisions, and emit a rigidly structured document: PROJECT_TYPE, TECHNOLOGY, SPEC_METADATA, USER_STORIES (each with ≥2 acceptance criteria, IDs in US-NNN form), REQUIREMENTS (REQ-NNN-USn-NNN), and NON_FUNCTIONAL (NFRs tagged by category). Every requirement must be specific and testable — no vague language. The stories and requirements are also stored into the knowledge graph.

Project Manager — U:PM (pm/volk.py, PMVolk)

The PM is the scope gate — advisory only, it warns but never blocks. Its PM_SYSTEM_PROMPT (SPEC-012) makes it count features, data entities, interfaces, and deployment concerns, then apply estimation heuristics (≈2 src + 1 test file per feature, LLM calls ≈ file count + 5, ≈3 min per source file) and raise a WARNING past its thresholds (>10 files, >8 features, >5 integrations, >20 LLM calls). It emits a single-line-JSON ESTIMATE, a SCOPE_RESULT, WARNINGS, and a TASK_SUMMARY. It also carries a GoalRegistry and GoalReportGenerator for SPEC-023 goal tracking.

UX Designer — U:Ux (ux/volk.py, UXVolk)

The UX volk only runs when the project has a UI. Its UX_SYSTEM_PROMPT casts it as a senior interaction designer whose output a frontend developer can implement without guessing. It follows a user-centered methodology: map user workflows (screen flows), build a component hierarchy, draw ASCII wireframes with data-source annotations, define design tokens (colors, typography, spacing scale, radii), and specify accessibility (WCAG 2.1 AA, keyboard nav, ARIA, 4.5:1 contrast). Output is a single UX_DESIGN: block with WORKFLOWS, COMPONENTS, WIREFRAMES, DESIGN_TOKENS, and ACCESSIBILITY sections.

Architect — U:Ar (architect/volk.py, ArchitectVolk)

The Architect is the principal designer, and in every profile it gets the strongest brain (Opus / v4-pro / kimi-thinking). Its ARCHITECT_PROMPT_TEMPLATE casts it as a principal software architect designing systems a junior can implement without ambiguity, using a five-step structured chain-of-thought (decomposition → dependency DAG → interface contracts → data flow → error boundaries) and Architecture Decision Records for every non-obvious choice. When existing source is injected it must design against it — reuse real components and import paths, don't reinvent — and for infrastructure concerns it must consult the design_patterns tool and cite the canonical cloud pattern's URL. Output includes an EXTERNAL_API section documenting the exact signatures of every third-party call, because the junior has no library docs but this spec. ArchitectVolk mixes in ArchitectProjectMixin and ArchitectContextMixin.

Junior — J:Junior (junior/volk.py, JuniorVolk)

The Junior plays two roles. First it is the design reviewer: before anyone writes code, its DESIGN_REVIEW_PROMPT makes it read the Architect's design and decide, in at most 3 cycles, whether it could implement the design right now without guessing. It runs a task-fidelity check (does the architecture actually address the stated task?) and a checklist — import paths, function signatures, dependency order, pyproject dependencies, FILE_TREE↔API_SPEC consistency — asking the minimum blocking questions (up to 5 on cycle 1, 3 on cycle 2, then forced READY). Second, it is a code generator: it generates code through the configured driver backend, validates dependencies afterward, and scans the workspace for the files it created. The CodeDirector delegates its fix_issues work down to J:Junior.

CodeDirector — U:Cd (codedirector/volk.py, CodeDirectorVolk)

The CodeDirector is the senior engineer who turns the approved design into real files on disk. Its CODEDIRECTOR_SYSTEM_PROMPT gives it a full tool loop — read_file, write_file, list_dir, search_code, ast_query, run_shell — and a concrete process: read the FILE_TREE/API_SPEC, search the codebase for existing patterns, plan the order (interfaces → models → services → CLI/API), write each file complete (never stubs), and verify syntax with py_compile after each write. It emits an IMPLEMENTATION_PLAN, a FILES_CREATED list, a TASK_SUMMARY, and READY_FOR_REVIEW. It also runs a cross-context SELF_REVIEW_PROMPT (syntax → imports → API correctness → file completeness → entry point, up to 3 cycles) before shipping.

QA — U:Qa (qa/volk.py, QaVolk)

The QA volk is a senior QA engineer that generates production-grade pytest suites and reviews the code. Its QA_SYSTEM_PROMPT enforces the project's hard test standards: pytest only, zero mocking (no unittest.mock, no custom Fake/Stub classes — real behavior only), Python 3.14+ idioms, os.getenv for env vars, and a @traces decorator on every test linking back to the source requirement IDs. It emits TEST_FILE blocks, a REVIEW_SUMMARY, and a TEST_RESULT: PASS|FAIL. A separate CODE_REVIEW_PROMPT runs a structured Google-style code review. The volk composes several mixins — AutofixMixin, FailureContextMixin, DepInstallMixin, TestGenMixin — to auto-install deps, gather failure context, and generate/repair tests.

Compliance — U:Cp (compliance/volk.py, ComplianceVolk)

Compliance is the tail of the pipeline and the only fully deterministic volk — it makes no LLM calls. It runs after QA passes and executes a fixed 7-step pipeline (compliance/_pipeline.py): scan @traces decorators across source and tests, load requirements from the knowledge graph, generate a Requirements Traceability Matrix, sync code nodes into the KG, check design-vs-code compliance, persist the RTM to disk and the KG, and produce a human-readable report. It carries a configurable compliance_threshold.

Documentor — U:Do (documentor/volk.py, DocumentorVolk)

The Documentor is the technical writer. Its DOCUMENTOR_SYSTEM_PROMPT casts it as a documentation engineer handling six work types — generate-new, update-existing, generate-spec (SPEC-XXX), generate-flow (Mermaid), generate-README, and generate-API-docs. It uses the same read/search/AST tools to understand the codebase before writing, follows the project's doc standards (Markdown, the 18-section spec template, "Last Updated"/"Specs Referenced" sections), and must call validate_mermaid on any diagram before embedding it. It emits DOC_TYPE, DOC_PATH, DOC_SUMMARY, TRACES, TASK_SUMMARY, and the full CONTENT.

Senior Dev — U:SD (senior_dev/agent.py, SeniorDevAgent)

The Senior Dev is the out-of-band firefighter — it does not sit in the main line. It activates when the goal runner detects oscillation: fixing issue A keeps breaking issue B and iterations fail to converge. Its SENIOR_DEV_PROMPT casts it as a principal engineer debugging systemic pipeline failures. It reads the last three iteration conversations, identifies the root-cause pattern (wrong architecture, missing dependency, bad API assumption, circular import…), and outputs a ROOT_CAUSE, 3–5 CONSTRAINTS, and a REVISED_INTENT_ADDENDUM — an addendum, not a rewrite — that gets folded back into the Concierge's intent to break the loop. It uses a top reasoning brain (Opus / v4-pro).

Why it holds together

Three properties make this a team rather than a prompt zoo. First, one identity contract — compose_persona guarantees every volk knows it is one member of a named crew, communicating over CXP and observed by the orchestrator. Second, one brain registry — spike-profiles.yaml maps aliases to models, so the whole fleet re-brains with a single env var and no code change. Third, structured, machine-consumable handoffs — each volk emits output in the exact labeled format the next volk parses, and each names its escalation_target (or branches like the PM and QA do), so the convoy moves without a human stitching packets together. Intent enters at the Concierge; tested, traced, documented software leaves at Compliance.


Grounded in src/orchestrata_ultimate/agents/volks/ and configs/spike-profiles.yaml. Packet 2026-10-18 — budget enforcement + progress/iteration reporting (SPEC-012 US-003/004/005). What changed: new pm/budget.py (PMConfig spec defaults, crossing-triggered BudgetTracker — budget_warning at 80%, budget_exceeded at 100%, edge-triggered; 5-minute iteration_stalled detection; structured summary builder) and PMVolk emission wiring (progress_update at stage transitions, budget/stall/summary events over the volk observable + CXP, iteration_summary persisted to the project conversation.md; PMConfig scope-threshold backstop). Where: src/orchestrata_ultimate/agents/volks/pm/budget.py, pm/volk.py, orchestrator/pipeline_runner.py (_notify_stage_pm/_notify_pm_iteration_end feed U:PM at every stage and at run end). Also fixed the _detect_has_ui false positive ("ui" inside "build") via whole-word matching. Tests: tests/agents/volks/pm/test_budget_tracking.py (19), tests/orchestrator/test_pipeline_runner_pm_notify.py (3); budget.py 100% coverage. Traces REQ-012-051..056. Commit: 09da62f34506e80ccbedf6ed2759221374752d52.