|
1 | 1 | # Architecture |
2 | 2 |
|
3 | | -HalfSeed separates orchestration from model access. |
| 3 | +HalfSeed separates orchestration from model access. This document is |
| 4 | +the high-level tour; the precise data and execution model lives in |
| 5 | +[graph-workflow-spec.md](graph-workflow-spec.md). |
4 | 6 |
|
5 | | -## Workflow |
| 7 | +## Two layers |
6 | 8 |
|
7 | | -1. `Principal` converts the human question into a structured research brief. |
8 | | -2. `Analytical`, `Numerical`, and `Literature` agents work from the same brief. |
9 | | -3. `Skeptic` critiques every artifact and adds failure modes. |
10 | | -4. `Analytical` and `Numerical` perform one revision pass using the critiques. |
11 | | -5. `Curator` filters and ranks artifacts with a deterministic budget guard. |
12 | | -6. `Presentation` produces a concise research memo. |
13 | | -7. `Principal` performs a final user-facing pass. |
| 9 | +``` |
| 10 | +┌────────────────────────────────────────────────────────────┐ |
| 11 | +│ Orchestration (this repo) │ |
| 12 | +│ • ProjectArchitecture: a DAG of agents and edges │ |
| 13 | +│ • Director: plans iterations and decides when to stop │ |
| 14 | +│ • Workflow: turns the graph into LLM calls per iteration │ |
| 15 | +└─────────────────────────┬──────────────────────────────────┘ |
| 16 | + │ ChatBackend protocol |
| 17 | +┌─────────────────────────▼──────────────────────────────────┐ |
| 18 | +│ Model access │ |
| 19 | +│ • DeepSeekChatBackend (live) │ |
| 20 | +│ • OpenAI / Anthropic via ProviderRouter (live) │ |
| 21 | +│ • RuleBasedBackend (offline, deterministic for tests) │ |
| 22 | +└────────────────────────────────────────────────────────────┘ |
| 23 | +``` |
| 24 | + |
| 25 | +The boundary is the `ChatBackend` protocol — anything below it is |
| 26 | +"how to talk to a model", anything above it is "what to ask it". |
| 27 | + |
| 28 | +## Workflow shape |
| 29 | + |
| 30 | +A project's workflow is a **graph of agents** edited in the web UI. |
| 31 | +The graph is a DAG; the system enforces this at validation time. |
| 32 | + |
| 33 | +The default architecture looks like: |
| 34 | + |
| 35 | +``` |
| 36 | +Director |
| 37 | + ├─→ Analytical (specialist) ─┐ |
| 38 | + ├─→ Numerical (specialist) ─┼─→ Skeptic ─→ Curator ─→ Presentation |
| 39 | + └─→ Literature (specialist) ─┘ |
| 40 | +``` |
| 41 | + |
| 42 | +Plus `Principal`, which sits at the head of the graph (it issues the |
| 43 | +brief into the graph) and is also called by the runtime *outside* the |
| 44 | +graph for the final user-facing answer. |
| 45 | + |
| 46 | +### What edges mean |
14 | 47 |
|
15 | | -## Why This Shape |
| 48 | +A → B means exactly: **"A's output flows into B's input on this iteration."** |
| 49 | +Edges have no labels, no payload fields, no "purpose" — wires are wires; |
| 50 | +all behavior is on the nodes (each node's `mission` and `output_contract` |
| 51 | +free-text fields). See [graph-workflow-spec.md §3](graph-workflow-spec.md) |
| 52 | +for the rationale and §9 for why edge-level prompts were rejected. |
16 | 53 |
|
17 | | -The design avoids unbounded group chat. Every internal message is converted into |
18 | | -a `ResearchArtifact`, and the curator has a hard `max_items` budget. This makes |
19 | | -agent output reviewable, testable, and easier to visualize later. |
| 54 | +When the user removes an edge in the architecture editor, the runtime |
| 55 | +genuinely stops flowing those artifacts to the downstream node — see |
| 56 | +`runtime/edge_filter.py`. |
| 57 | + |
| 58 | +### What's outside the graph |
| 59 | + |
| 60 | +Some behaviors are runtime mechanisms, not graph-expressible: |
| 61 | + |
| 62 | +- **Iteration loop.** The graph is a DAG; multi-iteration loops are |
| 63 | + the Director re-running the whole graph for another round. The |
| 64 | + Director's `should_stop` decision sits outside the graph. |
| 65 | +- **Attack-vector market.** When ≥2 specialists share an upstream, |
| 66 | + the runtime auto-runs a "pick distinct angles" protocol before |
| 67 | + their layer executes. |
| 68 | +- **Cross-iteration context.** `prior_iteration_summary`, |
| 69 | + `open_threads`, `rejected_claims`, the artifact pool — auto-injected |
| 70 | + into every node's prompt, not drawn as edges. |
| 71 | +- **Side effects.** Numerical sandbox runs and Writer's edits to |
| 72 | + `paper.tex` happen as post-processing hooks attached to the |
| 73 | + relevant role kinds. |
| 74 | + |
| 75 | +Spec [§5](graph-workflow-spec.md) covers each of these in detail. |
| 76 | + |
| 77 | +## Why this shape |
| 78 | + |
| 79 | +The design avoids unbounded group chat. Every internal message is |
| 80 | +converted into a `ResearchArtifact`, and the curator has a hard |
| 81 | +`max_items` budget. Output is reviewable, testable, and visualizable. |
| 82 | + |
| 83 | +Validation rules (cycles, duplicate singletons, unreachable specialists, |
| 84 | +etc.) run server-side and surface in the architecture editor; the |
| 85 | +"Run iteration" button is disabled when the graph has errors. See |
| 86 | +`architecture_validate.py` and spec §6 for the full rule list. |
20 | 87 |
|
21 | 88 | ## Tools |
22 | 89 |
|
23 | 90 | HalfSeed currently has two non-visual tools: |
24 | 91 |
|
25 | | -- `ArxivSearchClient` retrieves arXiv candidates and passes them as context to the Literature agent when `--literature-search` is enabled. |
26 | | -- `NumericalSandbox` runs project-owned numerical checks. The first built-in routine performs an RK4 smoke check for harmonic oscillator stability questions. |
27 | | - |
28 | | -The numerical sandbox does not run arbitrary model-written Python. New routines |
29 | | -should be explicit project code with tests. |
| 92 | +- `ArxivSearchClient` retrieves arXiv candidates and feeds them to |
| 93 | + whichever specialist matches the literature role kind when |
| 94 | + `--literature-search` is enabled. |
| 95 | +- `NumericalSandbox` runs project-owned numerical checks. The first |
| 96 | + built-in routine performs an RK4 smoke check for harmonic-oscillator |
| 97 | + stability questions. It does not run arbitrary model-written code; |
| 98 | + the sandbox that *does* run code artifacts is in `qa/sandbox.py` and |
| 99 | + is invoked as a Numerical-role side effect. |
30 | 100 |
|
31 | 101 | ## Stability |
32 | 102 |
|
33 | | -Live LLM calls are not trusted to always return perfect JSON. The workflow: |
| 103 | +Live LLM calls are not trusted to always return perfect JSON. The |
| 104 | +workflow: |
34 | 105 |
|
35 | 106 | - requests JSON mode from the backend; |
36 | 107 | - retries malformed JSON once with a compact regeneration prompt; |
37 | | -- normalizes common schema variations such as list-style specialist questions; |
38 | | -- falls back to low-confidence artifacts when an internal specialist still fails; |
39 | | -- retries transient DeepSeek HTTP errors such as 429 and 5xx responses. |
| 108 | +- normalizes common schema variations (e.g. list-style specialist |
| 109 | + questions); |
| 110 | +- falls back to low-confidence artifacts when an internal specialist |
| 111 | + still fails; |
| 112 | +- retries transient HTTP errors such as 429 and 5xx. |
40 | 113 |
|
41 | 114 | ## Persistence |
42 | 115 |
|
43 | | -`RunStore` writes both structured JSON and rendered Markdown for each run. The |
44 | | -CLI enables this with `--save-run`, using `runs/` by default. |
| 116 | +`ProjectStore` writes structured JSON for each iteration plus a |
| 117 | +rendered Markdown briefing. The CLI also exposes `RunStore` for the |
| 118 | +older one-shot `run()` path with `--save-run`. |
45 | 119 |
|
46 | | -## Backend Boundary |
| 120 | +## Backend boundary |
47 | 121 |
|
48 | | -All agents depend on `ChatBackend`. The current live backend is |
49 | | -`DeepSeekChatBackend`, but tests and offline demos use `RuleBasedBackend`. |
50 | | - |
51 | | -Future backend additions should implement: |
| 122 | +All agents depend on `ChatBackend`: |
52 | 123 |
|
53 | 124 | ```python |
54 | 125 | class ChatBackend(Protocol): |
55 | 126 | def complete(self, request: ChatRequest) -> ChatResponse: |
56 | 127 | ... |
57 | 128 | ``` |
58 | 129 |
|
59 | | -## Planned Extensions |
60 | | - |
61 | | -- Add persistent run storage. |
62 | | -- Add graph visualization for curator output. |
63 | | -- Add code execution tools for numerical checks. |
64 | | -- Add retrieval-backed literature search. |
65 | | -- Add role-specific model routing while keeping shared V4 as the default. |
| 130 | +The current live backends are `DeepSeekChatBackend` and the OpenAI/ |
| 131 | +Anthropic adapters routed via `ProviderRouter`. Tests and offline |
| 132 | +demos use `RuleBasedBackend`. New backends only need to implement |
| 133 | +the protocol. |
| 134 | + |
| 135 | +## Pointers |
| 136 | + |
| 137 | +| topic | start here | |
| 138 | +|---|---| |
| 139 | +| precise graph model + execution algorithm | [graph-workflow-spec.md](graph-workflow-spec.md) | |
| 140 | +| validator rules | `architecture_validate.py` + spec §6 | |
| 141 | +| edge-driven artifact filtering | `runtime/edge_filter.py` | |
| 142 | +| graph executor (topo sort, layered run) | `runtime/graph_executor.py` | |
| 143 | +| role definitions and singleton constraints | `agents/roles.py` | |
| 144 | +| Director (iteration planner) | `agents/director.py` | |
| 145 | +| paper rendering | `publish/paper.py` and `publish/paper_edits.py` | |
0 commit comments