Add your own architecture¶
A 5-step recipe for getting a new pattern into the library + notebook + tests + docs. Mirrors how every architecture in the catalogue was built.
1. Write the architecture class¶
Create src/agentic_architectures/architectures/<your_name>.py:
"""<one-line description>.
Origin: <citation>
"""
from __future__ import annotations
import operator
from typing import Annotated, Any, TypedDict
from langgraph.graph import END, START, StateGraph
from pydantic import BaseModel, Field
from agentic_architectures.architectures.base import Architecture, ArchitectureResult
# 1. State schema
class YourState(TypedDict, total=False):
task: str
# ... your state fields
history: Annotated[list[dict[str, Any]], operator.add]
final_output: str
# 2. Pydantic schemas (one per structured-output LLM call)
class _YourSchema(BaseModel):
answer: str = Field(description="...")
# use Literal[...] / bool / int with bounds for any deciding signals — NOT a numeric score
# 3. The architecture
class YourArchitecture(Architecture):
name = "your_architecture"
description = "..."
reference = "https://arxiv.org/abs/..."
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
# ... bind structured-output runnables here
self._solver = self.llm.with_structured_output(_YourSchema)
def _your_node(self, state: YourState) -> dict[str, Any]:
# ... node logic
return {"final_output": "...", "history": [{"stage": "your_node"}]}
def build(self) -> Any:
g: StateGraph = StateGraph(YourState)
g.add_node("your_node", self._your_node)
g.add_edge(START, "your_node")
g.add_edge("your_node", END)
return g.compile()
def run(self, task: str, **kwargs: Any) -> ArchitectureResult:
graph = self.build()
final_state = graph.invoke({"task": task}, config={"recursion_limit": 25})
return ArchitectureResult(
output=final_state.get("final_output", ""),
trace=final_state.get("history", []),
metadata={...}, # your numeric/boolean signals for §9 commentary
)
2. Register in __init__.py¶
# src/agentic_architectures/architectures/__init__.py
from agentic_architectures.architectures.your_name import YourArchitecture
__all__ = [
...,
"YourArchitecture", # alphabetical
]
3. Smoke-test before papermilling¶
PYTHONIOENCODING=utf-8 .venv/Scripts/python.exe -c \
"from agentic_architectures.architectures import YourArchitecture; \
r = YourArchitecture().run('test'); print(r.metadata); print(r.output)"
4. Write the notebook builder¶
Use scripts/build_NN_<existing>.py (e.g. build_15_rlhf.py) as a starting template. Generate the canonical 11-section structure:
- Title + TL;DR + properties table
- Mermaid architecture diagram
- Theory
- Setup
- Library walkthrough
- State schema
- Build the graph (with PNG render)
- Live run (with machine-readable
print(f"KEY=value")for tailor) - PLACEHOLDER —
## 9 · What we just observed(tailor will fill) - Try other providers / variations
- Failure modes + safety + extensions + references
Build it:
5. Execute + tailor¶
.venv/Scripts/python.exe -m papermill notebooks/NN_your_name.ipynb \
notebooks/NN_your_name.ipynb \
--kernel python3
.venv/Scripts/python.exe scripts/tailor_NN_commentary.py
The tailor regex-parses your machine-readable print() lines and rewrites §9 with concrete numbers. See scripts/tailor_15_commentary.py for the template.
6. Add tests¶
The test framework auto-picks up your architecture via the registry sweep:
# tests/unit/test_registry.py — already parametrized over A.__all__
# So your class gets 3 free tests: metadata / instantiate / build.
If your architecture has constructor args beyond llm=, add a row to EXTRA_KWARGS in test_registry.py.
Optional but recommended: a dedicated unit test in tests/unit/test_pure_python.py for any pure-Python helpers (deterministic-picker functions).
And one integration test:
# tests/integration/test_integration_all.py
def test_your_architecture_real() -> None:
from agentic_architectures.architectures import YourArchitecture
arch = YourArchitecture(llm=_llm())
r = arch.run("...")
assert r.output
7. Add to the benchmark¶
# benchmarks/tasks.yaml
- id: your_task
kind: ...
prompt: |
...
expected_contains: ["..."]
architectures:
- YourArchitecture
Run python benchmarks/run_benchmark.py --only YourArchitecture to confirm the cell renders.
8. Add to docs nav¶
That's it. The mkdocs-jupyter plugin will render your notebook as a docs page with the same structure as every other architecture — no separate MD file needed.