zoobzio February 20, 2026 Edit this page

Core Concepts

cogito is built around two core concepts: Thought and Note.

Thought

A Thought represents the rolling context of a reasoning chain. It maintains:

  • An append-only log of Notes
  • A tracking cursor for published vs unpublished Notes
  • An LLM session for conversation continuity
// Create a thought
thought := cogito.New(ctx, "analyse document")

// Thoughts have identity
fmt.Println(thought.ID)       // Auto-generated UUID
fmt.Println(thought.TraceID)  // Auto-generated trace ID
fmt.Println(thought.Intent)   // "analyse document"

Thought Lifecycle

  1. Creation - New() creates a thought with auto-generated ID
  2. Note Accumulation - Primitives add notes via SetContent()
  3. Processing - Primitives read context from notes, call LLM, write results
  4. Publication - Notes are marked as "published" after being sent to LLM

Cloning for Parallel Processing

Thoughts can be cloned for parallel execution:

clone := thought.Clone()
// Clone has independent notes and session
// Modifications don't affect the original

Note

Notes are atomic units of information in the reasoning chain:

type Note struct {
    ID        string            // Auto-generated UUID
    ThoughtID string            // Parent thought
    Key       string            // Lookup key
    Content   string            // String content (everything is text in LLM space)
    Metadata  map[string]string // Structured extension
    Source    string            // Origin primitive
    Created   time.Time         // Timestamp
}

Adding Notes

// Simple content
thought.SetContent(ctx, "summary", "Customer requests refund", "analyze")

// With metadata
thought.SetNote(ctx, "decision", "approved", "decide", map[string]string{
    "confidence": "0.95",
    "reasoning":  "Clear policy violation",
})

Reading Notes

// Get content by key
content, err := thought.GetContent("summary")

// Get full note
note, ok := thought.GetNote("decision")
if ok {
    fmt.Println(note.Metadata["confidence"])
}

// Get all notes
notes := thought.AllNotes()

Published vs Unpublished

Notes track whether they've been sent to the LLM:

// Get notes not yet sent to LLM
unpublished := thought.GetUnpublishedNotes()

// After processing, mark as published
thought.MarkNotesPublished(ctx)

This prevents redundant context in multi-step pipelines.

Provider

Providers handle LLM communication:

type Provider interface {
    Call(ctx context.Context, messages []zyn.Message, temperature float32) (*zyn.ProviderResponse, error)
    Name() string
}

Resolution Hierarchy

  1. Step-level: .WithProvider(p)
  2. Context: cogito.WithProvider(ctx, p)
  3. Global: cogito.SetProvider(p)
// Global default
cogito.SetProvider(defaultProvider)

// Context override
ctx = cogito.WithProvider(ctx, specialProvider)

// Step override
decide := cogito.NewDecide("key", "question").WithProvider(customProvider)

Next Steps