File size: 4,979 Bytes
e706de2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# Code Explanation: aot-agent.js

This example demonstrates the **Atom of Thought** prompting pattern using a mathematical calculator as the domain.

## Three-Phase Architecture

### Phase 1: Planning (LLM)
```javascript

async function generatePlan(userPrompt) {

    const grammar = await llama.createGrammarForJsonSchema(planSchema);

    const planText = await session.prompt(userPrompt, { grammar });

    return grammar.parse(planText);

}

```

**Key points:**
- LLM outputs **structured JSON** (enforced by grammar)
- LLM does NOT execute calculations
- Each atom represents one operation
- Dependencies are explicit (`dependsOn` array)

**Example output:**
```json

{

  "atoms": [

    {"id": 1, "kind": "tool", "name": "add", "input": {"a": 15, "b": 7}},

    {"id": 2, "kind": "tool", "name": "multiply", "input": {"a": "<result_of_1>", "b": 3}},

    {"id": 3, "kind": "tool", "name": "subtract", "input": {"a": "<result_of_2>", "b": 10}},

    {"id": 4, "kind": "final", "name": "report", "dependsOn": [3]}

  ]

}

```

### Phase 2: Validation (System)
```javascript

function validatePlan(plan) {

    const allowedTools = new Set(Object.keys(tools));

    

    for (const atom of plan.atoms) {

        if (ids.has(atom.id)) throw new Error(`Duplicate ID`);

        if (atom.kind === "tool" && !allowedTools.has(atom.name)) {

            throw new Error(`Unknown tool: ${atom.name}`);

        }

    }

}

```

**Validates:**
- No duplicate atom IDs
- Only allowed tools are referenced
- Dependencies make sense
- JSON structure is correct

### Phase 3: Execution (System)
```javascript

function executePlan(plan) {

    const state = {};

    

    for (const atom of sortedAtoms) {

        // Resolve dependencies

        let resolvedInput = {};

        for (const [key, value] of Object.entries(atom.input)) {

            if (value.startsWith('<result_of_')) {

                const refId = parseInt(value.match(/\d+/)[0]);

                resolvedInput[key] = state[refId];

            }

        }

        

        // Execute

        state[atom.id] = tools[atom.name](resolvedInput.a, resolvedInput.b);

    }

}

```

**Key behaviors:**
- Executes atoms in order (sorted by ID)
- Resolves `<result_of_N>` references from state
- Each atom stores its result in `state[atom.id]`
- Execution is **deterministic** (same plan + same state = same result)

## Why This Matters

### Comparison with ReAct

| Aspect | ReAct | Atom of Thought |
|--------|-------|-----------------|
| **Planning** | Implicit (in LLM reasoning) | Explicit (JSON structure) |
| **Execution** | LLM decides next step | System follows plan |
| **Validation** | None | Before execution |
| **Debugging** | Hard (trace through text) | Easy (inspect atoms) |
| **Testing** | Hard (mock LLM) | Easy (test executor) |
| **Failures** | May hallucinate | Fail at specific atom |

### Benefits

1. **No hidden reasoning**: Every operation is an explicit atom
2. **Testable**: Execute plan without LLM involvement
3. **Debuggable**: Know exactly which atom failed
4. **Auditable**: Plan is a data structure, not text
5. **Deterministic**: Same input = same output (given same plan)

## Tool Implementation

Tools are **pure functions** with no side effects:
```javascript

const tools = {

    add: (a, b) => {

        const result = a + b;

        console.log(`EXECUTING: add(${a}, ${b}) = ${result}`);

        return result;

    },

    // ... more tools

};

```

**Why pure functions?**
- Easy to test
- Easy to replay
- No hidden state
- Composable

## State Flow
```

User Question

      ↓

[LLM generates plan]

      ↓

{atoms: [...]} ← JSON plan

      ↓

[System validates]

      ↓

Plan valid

      ↓

[System executes atom 1] β†’ state[1] = result

      ↓

[System executes atom 2] β†’ state[2] = result (uses state[1])

      ↓

[System executes atom 3] β†’ state[3] = result (uses state[2])

      ↓

Final Answer

```

## Error Handling
```javascript

// Atom validation fails β†’ re-prompt LLM

validatePlan(plan); // throws if invalid



// Tool execution fails β†’ stop at that atom

if (b === 0) throw new Error("Division by zero");



// Dependency missing β†’ clear error message

if (!(depId in state)) {

    throw new Error(`Atom ${atom.id} depends on incomplete atom ${depId}`);

}

```

## When to Use AoT

βœ… **Use AoT when:**
- Execution must be auditable
- Failures must be recoverable
- Multiple steps with dependencies
- Testing is important
- Compliance matters

❌ **Don't use AoT when:**
- Single-step tasks
- Creative/exploratory tasks
- Brainstorming
- Natural conversation

## Extension Ideas

1. **Add compensation atoms** for rollback
2. **Add retry logic** per atom
3. **Parallelize independent atoms** (atoms with no shared dependencies)
4. **Persist plan** for debugging
5. **Visualize atom graph** (dependency tree)