docs: Complete architecture documentation for technical and non-technical readers
Browse files- ARCHITECTURE.md +465 -0
ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Purpose Agent β Architecture Documentation
|
| 2 |
+
|
| 3 |
+
> For developers building on the framework, researchers understanding the theory, and anyone curious about how self-improving agents work.
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## Table of Contents
|
| 8 |
+
|
| 9 |
+
1. [What Is Purpose Agent?](#1-what-is-purpose-agent)
|
| 10 |
+
2. [The Big Idea (No Jargon)](#2-the-big-idea)
|
| 11 |
+
3. [How It Works β Step by Step](#3-how-it-works)
|
| 12 |
+
4. [Architecture Map](#4-architecture-map)
|
| 13 |
+
5. [The Core Engine](#5-the-core-engine)
|
| 14 |
+
6. [The V2 Safety Kernel](#6-the-v2-safety-kernel)
|
| 15 |
+
7. [Research Implementations](#7-research-implementations)
|
| 16 |
+
8. [Breakthroughs](#8-breakthroughs)
|
| 17 |
+
9. [User-Facing Layers](#9-user-facing-layers)
|
| 18 |
+
10. [How Models Are Handled](#10-how-models-are-handled)
|
| 19 |
+
11. [The Research Behind It](#11-the-research)
|
| 20 |
+
12. [For Contributors](#12-for-contributors)
|
| 21 |
+
|
| 22 |
+
---
|
| 23 |
+
|
| 24 |
+
## 1. What Is Purpose Agent?
|
| 25 |
+
|
| 26 |
+
Purpose Agent is a Python framework that builds AI agents that **get better with experience** β without retraining the underlying AI model.
|
| 27 |
+
|
| 28 |
+
Traditional AI agents run the same way every time. Purpose Agent is different: after each task, it extracts lessons from what worked and what didn't, tests those lessons for safety, and uses them to perform better next time.
|
| 29 |
+
|
| 30 |
+
**Think of it like this:** A new employee follows the company handbook. After their first week, they have personal notes β shortcuts they discovered, mistakes they won't repeat, tips from colleagues. Those notes make them better at their job without changing who they are. Purpose Agent does this for AI.
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
## 2. The Big Idea
|
| 35 |
+
|
| 36 |
+
### For Non-Technical Readers
|
| 37 |
+
|
| 38 |
+
```
|
| 39 |
+
You give it a purpose β It builds a team β It does the work β It learns β Next time is better
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
**You say:** "Help me write Python code."
|
| 43 |
+
**It builds:** An architect (plans), a coder (writes), and a tester (reviews).
|
| 44 |
+
**It runs:** The coder writes fibonacci. The tester checks it. A critic scores the work.
|
| 45 |
+
**It learns:** "When writing recursive functions, check base cases first." This lesson is saved.
|
| 46 |
+
**Next time:** The coder starts by checking base cases. It's faster and more reliable.
|
| 47 |
+
|
| 48 |
+
### For Technical Readers
|
| 49 |
+
|
| 50 |
+
The framework implements a **Purpose-MDP** β a Markov Decision Process where:
|
| 51 |
+
|
| 52 |
+
- A **Purpose Function Ξ¦(s)** evaluates every state transition on a 0-10 scale
|
| 53 |
+
- An **Optimizer** distills successful trajectories into reusable heuristics
|
| 54 |
+
- Heuristics are ranked by **Q-values** (how often they helped) and selected via **Mixture-of-Heuristics** (sparse activation, like MoE)
|
| 55 |
+
- An **immune system** scans every new heuristic for prompt injection, score manipulation, and other threats
|
| 56 |
+
- **Memory CI pipeline** quarantines, tests, and promotes heuristics before they affect agent behavior
|
| 57 |
+
|
| 58 |
+
This is **Potential-Based Reward Shaping** (Ng et al., 1999) applied to LLM agents, with formal convergence guarantees. See [PURPOSE_LEARNING.md](PURPOSE_LEARNING.md).
|
| 59 |
+
|
| 60 |
+
---
|
| 61 |
+
|
| 62 |
+
## 3. How It Works β Step by Step
|
| 63 |
+
|
| 64 |
+
Here's what happens when you run `team.run("Write a fibonacci function")`:
|
| 65 |
+
|
| 66 |
+
### Step 1: The Actor Decides
|
| 67 |
+
|
| 68 |
+
The Actor module receives:
|
| 69 |
+
- The **purpose** ("Write a fibonacci function")
|
| 70 |
+
- The **current state** (empty β no code written yet)
|
| 71 |
+
- Any **learned heuristics** from past runs
|
| 72 |
+
|
| 73 |
+
It generates a thought process and an action:
|
| 74 |
+
> "I should write a function that handles base cases fib(0)=0 and fib(1)=1, then use iteration for the general case."
|
| 75 |
+
> β Action: `submit_code` with the Python implementation.
|
| 76 |
+
|
| 77 |
+
### Step 2: The Environment Executes
|
| 78 |
+
|
| 79 |
+
The code is run against test cases. The environment returns a new state:
|
| 80 |
+
> "Tests: 4/4 ALL PASSED"
|
| 81 |
+
|
| 82 |
+
### Step 3: The Purpose Function Scores
|
| 83 |
+
|
| 84 |
+
A **separate LLM call** (not the same as the actor) evaluates the transition:
|
| 85 |
+
- Ξ¦(state_before) = 0.0 (nothing done)
|
| 86 |
+
- Ξ¦(state_after) = 10.0 (all tests pass)
|
| 87 |
+
- Delta = +10.0 (huge improvement)
|
| 88 |
+
- Evidence: "Tests changed from 0/4 to 4/4"
|
| 89 |
+
|
| 90 |
+
The Purpose Function has **7 anti-gaming rules** that prevent the agent from tricking itself into thinking it's doing well when it isn't.
|
| 91 |
+
|
| 92 |
+
### Step 4: The Optimizer Extracts Heuristics
|
| 93 |
+
|
| 94 |
+
After the task, the Optimizer looks at the trajectory and extracts reusable patterns:
|
| 95 |
+
- **Strategic:** "When writing {function_type} functions, handle edge cases first, then iterate."
|
| 96 |
+
- **Procedural:** "1. Read test cases. 2. Handle base cases. 3. Implement general case. 4. Submit."
|
| 97 |
+
- **Tool tip:** "When submitting code, check boundary conditions: 0, 1, empty, negative."
|
| 98 |
+
|
| 99 |
+
### Step 5: Safety Checks
|
| 100 |
+
|
| 101 |
+
Every new heuristic goes through the **immune system**:
|
| 102 |
+
- Is it a prompt injection? ("Ignore all previous instructions") β **REJECTED**
|
| 103 |
+
- Does it try to manipulate scores? ("Always score 10") β **REJECTED**
|
| 104 |
+
- Does it contain secrets? (API keys, passwords) β **REJECTED**
|
| 105 |
+
- Is it safe? ("Check base cases first") β **QUARANTINED** (pending replay test)
|
| 106 |
+
|
| 107 |
+
After passing replay testing β **PROMOTED** (active in future runs).
|
| 108 |
+
|
| 109 |
+
### Step 6: Next Run Benefits
|
| 110 |
+
|
| 111 |
+
When the agent runs again, the **Prompt Compiler** selects the top-K heuristics by:
|
| 112 |
+
- **Relevance** to the current task (embedding similarity)
|
| 113 |
+
- **Trust** (immune-scanned and verified)
|
| 114 |
+
- **Utility** (Q-value β how often it helped before)
|
| 115 |
+
|
| 116 |
+
These are injected into the prompt. The agent is now better without any model retraining.
|
| 117 |
+
|
| 118 |
+
---
|
| 119 |
+
|
| 120 |
+
## 4. Architecture Map
|
| 121 |
+
|
| 122 |
+
```
|
| 123 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 124 |
+
β PURPOSE AGENT β
|
| 125 |
+
β β
|
| 126 |
+
β ββββ USER LAYER βββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 127 |
+
β β pa.purpose("...") β Team β team.run("...") β β
|
| 128 |
+
β β pa.Agent() pa.Graph() pa.parallel() pa.Conversation() β β
|
| 129 |
+
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ β
|
| 130 |
+
β β β
|
| 131 |
+
β ββββ CORE ENGINE βββββββββββββββββββββββββββββββββββΌβββββββββββββββ β
|
| 132 |
+
β β β β
|
| 133 |
+
β β Actor βββ Environment βββ Purpose Function (Ξ¦) β β
|
| 134 |
+
β β β β β β β
|
| 135 |
+
β β β β βΌ β β
|
| 136 |
+
β β β State s' Ξ¦(s) β Ξ¦(s') β β
|
| 137 |
+
β β β β β β β
|
| 138 |
+
β β β βΌ βΌ β β
|
| 139 |
+
β β β Experience Replay Optimizer β β
|
| 140 |
+
β β β β β β β
|
| 141 |
+
β β βββββ heuristics ββββββββββββββ β β
|
| 142 |
+
β β β β
|
| 143 |
+
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ β
|
| 144 |
+
β β β
|
| 145 |
+
β ββββ V2 SAFETY KERNEL βββββββββββββββββββββββββββββΌβββββββββββββββ β
|
| 146 |
+
β β β β
|
| 147 |
+
β β Immune System βββ Memory CI βββ Memory Store β β
|
| 148 |
+
β β (scan threats) (quarantine) (7 types Γ 5 statuses) β β
|
| 149 |
+
β β β β
|
| 150 |
+
β β Prompt Compiler βββ Token Budget βββ Credit Assignment β β
|
| 151 |
+
β β Trace System βββ JSONL logs βββ Offline analysis β β
|
| 152 |
+
β β RunMode βββ EVAL_TEST blocks all writes β β
|
| 153 |
+
β β β β
|
| 154 |
+
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ β
|
| 155 |
+
β β β
|
| 156 |
+
β ββββ INFRASTRUCTURE βββββββββββββββββββββββββββββββΌβββββββββββββββ β
|
| 157 |
+
β β β β
|
| 158 |
+
β β LLM Backends: OpenRouter β Groq β OpenAI β Ollama β HF β ... β β
|
| 159 |
+
β β Robust Parser: TOML β JSON β field extraction β regex β β
|
| 160 |
+
β β Tools: Calculator β PythonExec β ReadFile β WriteFile β β
|
| 161 |
+
β β Streaming β Observability β Cost Tracking β Registry β β
|
| 162 |
+
β β β β
|
| 163 |
+
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 164 |
+
ββββββββββββββββββββββββββββββββββββββββββββββοΏ½οΏ½οΏ½ββββββββββββββββββββββββββββ
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
---
|
| 168 |
+
|
| 169 |
+
## 5. The Core Engine
|
| 170 |
+
|
| 171 |
+
### Actor (`actor.py`)
|
| 172 |
+
The decision-maker. Given the current state and purpose, it decides what action to take.
|
| 173 |
+
|
| 174 |
+
**Key design:** The Actor doesn't evaluate itself. That's the Purpose Function's job. This separation prevents self-confirmation bias (you wouldn't let a student grade their own exam).
|
| 175 |
+
|
| 176 |
+
The Actor's prompt is **dynamically composed** from three tiers of memory:
|
| 177 |
+
- **Strategic:** High-level rules ("When coding, handle edge cases first")
|
| 178 |
+
- **Procedural:** Step-by-step procedures ("1. Read tests. 2. Handle bases. 3. Implement.")
|
| 179 |
+
- **Tool tips:** Action-specific advice ("When using submit_code, check boundaries")
|
| 180 |
+
|
| 181 |
+
### Purpose Function (`purpose_function.py`)
|
| 182 |
+
The critic. A separate LLM call that scores every state transition on a 0-10 scale.
|
| 183 |
+
|
| 184 |
+
**Seven anti-gaming rules:**
|
| 185 |
+
1. Evidence required β cite specific state changes
|
| 186 |
+
2. No credit for intentions β score actual results, not plans
|
| 187 |
+
3. No sycophancy β don't inflate scores to be encouraging
|
| 188 |
+
4. Monotonic scale β 0=nothing done, 10=task complete
|
| 189 |
+
5. Anti-gaming β flag superficial state manipulation
|
| 190 |
+
6. Consistency β same state gets same score (enforced by cache)
|
| 191 |
+
7. Confidence β uncertain evaluations get reduced weight
|
| 192 |
+
|
| 193 |
+
### Experience Replay (`experience_replay.py`)
|
| 194 |
+
Stores completed trajectories and retrieves relevant ones for future tasks.
|
| 195 |
+
|
| 196 |
+
**Two-phase retrieval** (from MemRL, arxiv:2601.03192):
|
| 197 |
+
1. **Recall:** Find trajectories similar to the current task (embedding similarity)
|
| 198 |
+
2. **Re-rank:** Order by Q-value utility (how useful was this memory when retrieved before?)
|
| 199 |
+
|
| 200 |
+
### Optimizer (`optimizer.py`)
|
| 201 |
+
Extracts reusable heuristics from successful trajectories.
|
| 202 |
+
|
| 203 |
+
Uses the **CER distillation pattern** (arxiv:2506.06698): abstract away specific details with `{variable}` placeholders so heuristics generalize across tasks.
|
| 204 |
+
|
| 205 |
+
### Orchestrator (`orchestrator.py`)
|
| 206 |
+
The main loop that ties everything together. For each step:
|
| 207 |
+
1. Actor decides β 2. Environment executes β 3. Critic scores β 4. Step recorded β 5. Check termination
|
| 208 |
+
|
| 209 |
+
After each task: store trajectory β optimize β sync heuristics to Actor memory.
|
| 210 |
+
|
| 211 |
+
---
|
| 212 |
+
|
| 213 |
+
## 6. The V2 Safety Kernel
|
| 214 |
+
|
| 215 |
+
V1 let the agent learn freely. V2 adds guardrails.
|
| 216 |
+
|
| 217 |
+
### Memory System (`memory.py`)
|
| 218 |
+
Seven memory types, each with different trust priors:
|
| 219 |
+
|
| 220 |
+
| Type | Example | Trust |
|
| 221 |
+
|------|---------|-------|
|
| 222 |
+
| `purpose_contract` | "Build a web scraper" | High (user-defined) |
|
| 223 |
+
| `user_preference` | "Always cite sources" | High (human-taught) |
|
| 224 |
+
| `skill_card` | "When coding, test edges first" | Medium (learned) |
|
| 225 |
+
| `episodic_case` | "fib(0)=0 was a tricky case" | Medium (observed) |
|
| 226 |
+
| `failure_pattern` | "Don't use recursion for large n" | Medium (learned from failure) |
|
| 227 |
+
| `critic_calibration` | "Score 7 for 3/4 tests passing" | Low (meta-learned) |
|
| 228 |
+
| `tool_policy` | "search: only use at target location" | Medium (learned) |
|
| 229 |
+
|
| 230 |
+
Five statuses: `candidate` β `quarantined` β `promoted` (or `rejected`) β `archived`.
|
| 231 |
+
|
| 232 |
+
### Immune System (`immune.py`)
|
| 233 |
+
Scans every candidate memory for 5 threat categories:
|
| 234 |
+
- **Prompt injection** β "Ignore previous instructions..."
|
| 235 |
+
- **Score manipulation** β "Always score 10..."
|
| 236 |
+
- **Tool misuse** β "subprocess.call('rm -rf /')..."
|
| 237 |
+
- **Privacy leaks** β API keys, emails, file paths
|
| 238 |
+
- **Scope overreach** β memory tries to affect all agents when it should be scoped
|
| 239 |
+
|
| 240 |
+
### Memory CI (`memory_ci.py`)
|
| 241 |
+
The promotion pipeline:
|
| 242 |
+
```
|
| 243 |
+
candidate β immune_scan() β quarantined β replay_test β promote/reject
|
| 244 |
+
```
|
| 245 |
+
No memory reaches the agent's prompt without passing every gate.
|
| 246 |
+
|
| 247 |
+
### Prompt Compiler (`compiler.py`)
|
| 248 |
+
Selects which memories to include under a token budget. Ranked by:
|
| 249 |
+
`score = 0.4 Γ relevance + 0.3 Γ trust + 0.3 Γ utility`
|
| 250 |
+
|
| 251 |
+
Returns `included_memory_ids` for credit assignment β only memories that were in the prompt get Q-value updates after the step.
|
| 252 |
+
|
| 253 |
+
### Trace System (`trace.py`)
|
| 254 |
+
Every run produces a JSONL trace β the raw material for debugging, evaluation, and memory extraction. Traces are append-only and immutable.
|
| 255 |
+
|
| 256 |
+
### RunMode (`v2_types.py`)
|
| 257 |
+
Three modes with strict enforcement:
|
| 258 |
+
- `LEARNING_TRAIN` β full read/write
|
| 259 |
+
- `LEARNING_VALIDATION` β read + staging writes
|
| 260 |
+
- `EVAL_TEST` β **no writes of any kind** (the only mode whose numbers you can report)
|
| 261 |
+
|
| 262 |
+
---
|
| 263 |
+
|
| 264 |
+
## 7. Research Implementations
|
| 265 |
+
|
| 266 |
+
Five papers implemented as standalone modules:
|
| 267 |
+
|
| 268 |
+
### Meta-Rewarding (`meta_rewarding.py`)
|
| 269 |
+
*From: arxiv:2407.19594 β Llama-3-8B: 22.9% β 39.4% on AlpacaEval*
|
| 270 |
+
|
| 271 |
+
A meta-judge evaluates the Purpose Function's own judgments. Good judgments become calibration examples in memory. The critic improves through in-context learning.
|
| 272 |
+
|
| 273 |
+
### Self-Taught Evaluators (`self_taught.py`)
|
| 274 |
+
*From: arxiv:2408.02666*
|
| 275 |
+
|
| 276 |
+
Generates synthetic contrast pairs (correct vs wrong evaluation) from traces. Creates an automatic curriculum: as the critic improves, the contrast pairs get harder.
|
| 277 |
+
|
| 278 |
+
### Prompt Optimizer (`prompt_optimizer.py`)
|
| 279 |
+
*From DSPy: arxiv:2310.03714 β +8% on GSM8K, +50% on BBH*
|
| 280 |
+
|
| 281 |
+
Instead of hand-crafting prompts, define signatures (`state, action β score, reasoning`) and let the optimizer bootstrap effective few-shot demonstrations by trial-and-error.
|
| 282 |
+
|
| 283 |
+
### LLM Compiler (`llm_compiler.py`)
|
| 284 |
+
*From: arxiv:2312.04511 β up to 3.7Γ latency speedup*
|
| 285 |
+
|
| 286 |
+
Instead of sequential tool calls (ReAct), plan ALL calls upfront as a DAG and execute independent ones in parallel.
|
| 287 |
+
|
| 288 |
+
### Retroformer (`retroformer.py`)
|
| 289 |
+
*From: arxiv:2308.02151*
|
| 290 |
+
|
| 291 |
+
Structured reflection on completed traces β extracts four types of memories (skills, failures, policies, observations). Replaces raw heuristic distillation with typed, safety-scanned memory extraction.
|
| 292 |
+
|
| 293 |
+
---
|
| 294 |
+
|
| 295 |
+
## 8. Breakthroughs
|
| 296 |
+
|
| 297 |
+
Six features that go beyond existing frameworks:
|
| 298 |
+
|
| 299 |
+
### B1: Self-Improving Critic
|
| 300 |
+
The Purpose Function's own quality improves over time. Meta-judging after each task generates calibration examples that make future scoring more accurate.
|
| 301 |
+
|
| 302 |
+
### B2: Mixture-of-Heuristics (MoH)
|
| 303 |
+
Like DeepSeek's Mixture-of-Experts: out of 100+ heuristics, only K=5 are activated per step. **Shared heuristics** (always active, like "check edge cases") + **routed heuristics** (task-specific, selected by QΓsimilarity). Knowledge grows; compute stays flat.
|
| 304 |
+
|
| 305 |
+
### B3: Hindsight Heuristic Relabeling
|
| 306 |
+
From HER (arxiv:1707.01495): when a task fails, instead of discarding the trajectory, ask "what DID this accomplish?" and extract heuristics for what was achieved. Learn from failures, not just successes.
|
| 307 |
+
|
| 308 |
+
### B4: Heuristic Evolution
|
| 309 |
+
Periodically generalize specific heuristics into abstract patterns:
|
| 310 |
+
- Before: "When fibonacci fails on 0, return 0"
|
| 311 |
+
- After: "When {function} fails on {boundary_value}, add an explicit base case"
|
| 312 |
+
|
| 313 |
+
Creates an automatic curriculum: specific β general β abstract.
|
| 314 |
+
|
| 315 |
+
### B5: Cross-Domain Transfer
|
| 316 |
+
Heuristics from coding tasks can help with different coding tasks. The `test_cross_domain_transfer()` function measures this: train on [fibonacci, factorial], test on [palindrome, fizzbuzz].
|
| 317 |
+
|
| 318 |
+
### B6: Adversarial Robustness
|
| 319 |
+
The `AdversarialHardener` generates 30 adversarial inputs (prompt injections, score hacks, API key leaks) and 10 benign inputs, tests the immune system against all of them. Current results: **93% catch rate, 0% false positive.**
|
| 320 |
+
|
| 321 |
+
---
|
| 322 |
+
|
| 323 |
+
## 9. User-Facing Layers
|
| 324 |
+
|
| 325 |
+
### Easy API (`easy.py`)
|
| 326 |
+
The `purpose()` function analyzes your description and builds the right team:
|
| 327 |
+
|
| 328 |
+
| You say | It builds |
|
| 329 |
+
|---------|-----------|
|
| 330 |
+
| "Write Python code" | architect + coder + tester |
|
| 331 |
+
| "Research papers" | researcher + analyst |
|
| 332 |
+
| "Write blog posts" | writer + editor |
|
| 333 |
+
| "Analyze data" | analyst + reporter |
|
| 334 |
+
| "Help me" | general assistant |
|
| 335 |
+
|
| 336 |
+
### Unified Capabilities (`unified.py`)
|
| 337 |
+
Five competing framework philosophies in one composable layer:
|
| 338 |
+
|
| 339 |
+
| Capability | Inspired By | Usage |
|
| 340 |
+
|-----------|-------------|-------|
|
| 341 |
+
| `Agent()` | OpenAI Agents SDK | One-liner agent creation |
|
| 342 |
+
| `Graph()` | LangGraph | Conditional branching, cycles, fan-out |
|
| 343 |
+
| `parallel()` | CrewAI | Concurrent task execution |
|
| 344 |
+
| `Conversation()` | AutoGen | Agent-to-agent message passing |
|
| 345 |
+
| `KnowledgeStore` | LlamaIndex | RAG as a tool |
|
| 346 |
+
|
| 347 |
+
### Robust Parser (`robust_parser.py`)
|
| 348 |
+
The universal solution to "LLMs can't reliably produce JSON":
|
| 349 |
+
- Tries TOML first (fewer tokens than JSON)
|
| 350 |
+
- Falls back to JSON
|
| 351 |
+
- Falls back to field extraction by regex
|
| 352 |
+
- Never crashes. Always returns something usable.
|
| 353 |
+
|
| 354 |
+
---
|
| 355 |
+
|
| 356 |
+
## 10. How Models Are Handled
|
| 357 |
+
|
| 358 |
+
### resolve_backend()
|
| 359 |
+
One function routes to any provider:
|
| 360 |
+
|
| 361 |
+
```python
|
| 362 |
+
resolve_backend("openrouter:meta-llama/llama-3.3-70b-instruct")
|
| 363 |
+
resolve_backend("groq:llama-3.3-70b-versatile")
|
| 364 |
+
resolve_backend("openai:gpt-4o")
|
| 365 |
+
resolve_backend("ollama:qwen3:1.7b") # Local, free
|
| 366 |
+
resolve_backend("hf:Qwen/Qwen3-32B")
|
| 367 |
+
resolve_backend("together:meta-llama/Llama-3.3-70B-Instruct-Turbo")
|
| 368 |
+
```
|
| 369 |
+
|
| 370 |
+
### SLM-Native Design
|
| 371 |
+
The framework was designed for small models (0.6B-3B params):
|
| 372 |
+
- **Grammar-constrained output** via Ollama (forces valid structure from any model)
|
| 373 |
+
- **Prompt compression** for small context windows (8K-32K)
|
| 374 |
+
- **Tool RAG** β only load relevant tools into the prompt (saves tokens)
|
| 375 |
+
- **TOML format** β ~fewer tokens than JSON
|
| 376 |
+
|
| 377 |
+
### _strip_thinking()
|
| 378 |
+
Handles reasoning models (Qwen3, DeepSeek-R1) that wrap output in `<think>` tags. Automatically strips the thinking and returns only the answer.
|
| 379 |
+
|
| 380 |
+
---
|
| 381 |
+
|
| 382 |
+
## 11. The Research
|
| 383 |
+
|
| 384 |
+
Every design decision traces to a published paper. The full list with citations, methodology sections, and implementation mapping is in [COMPILED_RESEARCH.md](COMPILED_RESEARCH.md).
|
| 385 |
+
|
| 386 |
+
The formal framework β **Purpose-MDP** with 5 axioms, 3 theorems, and convergence proofs β is in [PURPOSE_LEARNING.md](PURPOSE_LEARNING.md).
|
| 387 |
+
|
| 388 |
+
**Key theoretical result:** The self-improvement is a form of Potential-Based Reward Shaping (Ng et al., 1999). Our ΞΞ¦ = Ξ¦(s') - Ξ¦(s) preserves the optimal policy while providing dense per-step feedback. The heuristic library converges to a fixed point under bounded capacity.
|
| 389 |
+
|
| 390 |
+
---
|
| 391 |
+
|
| 392 |
+
## 12. For Contributors
|
| 393 |
+
|
| 394 |
+
### File Structure
|
| 395 |
+
|
| 396 |
+
```
|
| 397 |
+
purpose_agent/
|
| 398 |
+
βββ types.py # State, Action, Trajectory, Heuristic, PurposeScore
|
| 399 |
+
βββ llm_backend.py # LLMBackend ABC + HF, OpenAI, Mock + resolve_backend
|
| 400 |
+
βββ slm_backends.py # Ollama, llama-cpp, prompt compression, SLM registry
|
| 401 |
+
βββ robust_parser.py # Universal parser: TOML β JSON β regex (never crashes)
|
| 402 |
+
βββ actor.py # ReAct agent with 3-tier memory prompts
|
| 403 |
+
βββ purpose_function.py # Ξ¦(s) critic with 7 anti-gaming rules
|
| 404 |
+
βββ experience_replay.py # Two-phase retrieval (similarity β Q-value)
|
| 405 |
+
βββ optimizer.py # Trajectory β heuristic distillation
|
| 406 |
+
βββ orchestrator.py # Main step loop
|
| 407 |
+
βββ v2_types.py # RunMode, MemoryScope, PurposeScoreV2
|
| 408 |
+
βββ trace.py # JSONL execution traces
|
| 409 |
+
βββ memory.py # 7 MemoryKinds Γ 5 MemoryStatuses
|
| 410 |
+
βββ compiler.py # Token-budgeted prompt compilation
|
| 411 |
+
βββ immune.py # 5 threat scanners
|
| 412 |
+
βββ memory_ci.py # Quarantine β scan β test β promote/reject
|
| 413 |
+
βββ evalport.py # Pluggable evaluation protocol
|
| 414 |
+
βββ benchmark_v2.py # Train/val/test splits with ablation
|
| 415 |
+
βββ meta_rewarding.py # Self-improving critic (arxiv:2407.19594)
|
| 416 |
+
βββ self_taught.py # Synthetic critic training (arxiv:2408.02666)
|
| 417 |
+
βββ prompt_optimizer.py # DSPy-style bootstrap (arxiv:2310.03714)
|
| 418 |
+
βββ llm_compiler.py # Parallel tool DAG (arxiv:2312.04511)
|
| 419 |
+
βββ retroformer.py # Structured reflection (arxiv:2308.02151)
|
| 420 |
+
βββ breakthroughs.py # MoH, hindsight relabeling, heuristic evolution, etc.
|
| 421 |
+
βββ unified.py # Agent, Graph, parallel, Conversation, KnowledgeStore
|
| 422 |
+
βββ easy.py # purpose(), Team, quickstart wizard
|
| 423 |
+
βββ tools.py # Secure built-in tools
|
| 424 |
+
βββ streaming.py # Async + event streaming
|
| 425 |
+
βββ observability.py # Cost tracking, callbacks
|
| 426 |
+
βββ multi_agent.py # Agent teams with shared learning
|
| 427 |
+
βββ hitl.py # Human-in-the-loop + checkpointing
|
| 428 |
+
βββ evaluation.py # V1 benchmark runner
|
| 429 |
+
βββ registry.py # Plugin system
|
| 430 |
+
βββ __init__.py # 103 exports
|
| 431 |
+
βββ __main__.py # CLI entry point
|
| 432 |
+
```
|
| 433 |
+
|
| 434 |
+
### Adding a New LLM Provider
|
| 435 |
+
|
| 436 |
+
```python
|
| 437 |
+
# In your code (no core edits needed):
|
| 438 |
+
from purpose_agent import backend_registry, OpenAICompatibleBackend
|
| 439 |
+
|
| 440 |
+
backend_registry.register("my_provider",
|
| 441 |
+
lambda model, api_key: OpenAICompatibleBackend(
|
| 442 |
+
model=model, base_url="https://api.myprovider.com/v1", api_key=api_key
|
| 443 |
+
))
|
| 444 |
+
```
|
| 445 |
+
|
| 446 |
+
### Adding a New Tool
|
| 447 |
+
|
| 448 |
+
```python
|
| 449 |
+
from purpose_agent import FunctionTool
|
| 450 |
+
|
| 451 |
+
def my_search(query: str) -> str:
|
| 452 |
+
"""Search my database."""
|
| 453 |
+
return db.search(query)
|
| 454 |
+
|
| 455 |
+
tool = FunctionTool.from_function(my_search)
|
| 456 |
+
```
|
| 457 |
+
|
| 458 |
+
### Running Tests
|
| 459 |
+
|
| 460 |
+
```bash
|
| 461 |
+
python tests/test_core.py # 21 unit tests
|
| 462 |
+
python tests/launch_readiness.py # 119 comprehensive tests
|
| 463 |
+
python benchmarks/validate.py # Mock benchmark suite
|
| 464 |
+
python benchmarks/validate.py --quick # Fast smoke test
|
| 465 |
+
```
|