Architecture
This document describes the system design and architectural decisions in cogito.
Design Principles
1. Everything is Text
In LLM space, all information is fundamentally text-based. Notes store content as strings, and structured data is extracted through typed primitives like Analyze[T].
2. Append-Only Notes
Thoughts maintain an append-only log of Notes. If a key is reused, the new note becomes the current value, but history is preserved. This enables:
- Audit trails of reasoning
- Rollback to previous states
3. Context Accumulation
Each primitive in a pipeline reads unpublished notes, sends them to the LLM, and marks them as published. This prevents redundant context while maintaining conversation flow.
4. Two-Phase Reasoning
Primitives support optional introspection:
- Reasoning Phase - Deterministic (temperature 0) for consistent outputs
- Introspection Phase - Creative (temperature 0.7) for semantic summaries
Component Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Application │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Pipeline │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Sequence │ │ Filter │ │ Switch │ │Fallback │ │Concurrent│ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Primitives │
│ ┌────────┐ ┌────────┐ ┌──────────┐ ┌──────┐ ┌──────────┐ │
│ │ Decide │ │Analyze │ │Categorize│ │Assess│ │Prioritize│ │
│ └────────┘ └────────┘ └──────────┘ └──────┘ └──────────┘ │
│ ┌──────┐ ┌────────┐ ┌────────┐ │
│ │ Sift │ │Discern │ │Reflect │ │
│ └──────┘ └────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Thought │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Notes[] │ Session │ PublishedCount │ Intent │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Infrastructure │
│ ┌──────────┐ ┌──────────┐ │
│ │ Provider │ │ Signals │ │
│ │ (LLM) │ │(Capitan) │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
Primitive Processing Flow
Each primitive follows the same pattern:
┌─────────────────────────────────────────────────────────────┐
│ Primitive.Process() │
├─────────────────────────────────────────────────────────────┤
│ 1. Get unpublished notes from Thought │
│ 2. Render notes to context string │
│ 3. Resolve provider (step → context → global) │
│ 4. Build prompt with context │
│ 5. Call provider (reasoning phase, temp=0) │
│ 6. Parse structured response │
│ 7. Store result as Note │
│ 8. [Optional] Run introspection (temp=0.7) │
│ 9. Mark notes as published │
│ 10. Emit signals │
│ 11. Return modified Thought │
└─────────────────────────────────────────────────────────────┘
Concurrency Model
Thoughts are safe for concurrent reads but not concurrent writes:
// Safe: Concurrent reads
go func() { thought.GetContent("key1") }()
go func() { thought.GetContent("key2") }()
// Unsafe: Concurrent writes
go func() { thought.SetContent(ctx, "key1", "v1", "src") }() // Don't do this
go func() { thought.SetContent(ctx, "key2", "v2", "src") }() // Don't do this
// Safe: Clone for parallel processing
clone1 := thought.Clone()
clone2 := thought.Clone()
go func() { process(clone1) }()
go func() { process(clone2) }()
Observability
cogito emits capitan signals throughout execution:
| Signal | Description |
|---|---|
ThoughtCreated | New thought initialised |
StepStarted | Primitive processing began |
StepCompleted | Primitive processing succeeded |
StepFailed | Primitive processing failed |
NoteAdded | Note added to thought |
NotesPublished | Notes sent to LLM context |
Extension Points
Custom Primitives
Implement pipz.Chainable[*Thought]:
type MyPrimitive struct {
key string
}
func (p *MyPrimitive) Process(ctx context.Context, t *cogito.Thought) (*cogito.Thought, error) {
// Read context
notes := t.GetUnpublishedNotes()
// Process with LLM
provider, _ := cogito.ResolveProvider(ctx, nil)
// ...
// Store result
t.SetContent(ctx, p.key, result, "my_primitive")
t.MarkNotesPublished(ctx)
return t, nil
}
func (p *MyPrimitive) Name() pipz.Name { return pipz.Name(p.key) }
func (p *MyPrimitive) Close() error { return nil }
Performance Considerations
- Token Management - Use Compress/Truncate to limit context size
- Parallel Execution - Use Converge for independent processing paths
Next Steps
- API Reference - Complete API documentation