-
-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Eshan Roy edited this page Jun 16, 2026
·
4 revisions
M31 Autonomous (M31A) is a modular AI agent framework built in Go with a Bubble Tea TUI. It routes user prompts through a six-phase workflow engine, selects models by cost and quality, streams responses, and maintains full session history with cross-session learning.
The application is a single static binary compiled with CGO_ENABLED=0, ensuring maximum portability across platforms.
.
├── cmd/m31a/ # Binary entry point
│ ├── main.go # CLI flag parsing, dependency wiring, TUI launch
│ └── usage.go # Usage/help text generation
├── docs/ # User-facing documentation
├── internal/ # Private packages (not importable)
│ ├── codeintel/ # Code intelligence: project indexing, relevance scoring
│ ├── config/ # TOML config loader, validation, project context detection
│ ├── errors/ # Sentinel errors for the entire application
│ ├── fileutil/ # Atomic file write utilities
│ ├── git/ # Git operations abstraction (commit, diff, log, stash)
│ ├── log/ # Structured logging infrastructure (slog-based)
│ ├── provider/ # LLM provider abstraction layer
│ │ ├── openrouter/ # OpenRouter API client (300+ models)
│ │ └── zen/ # Zen API client (OpenCode gateway)
│ ├── tokens/ # tiktoken-based token counting and estimation
│ ├── tools/ # Tool registry, dispatcher, and all built-in tools
│ │ └── subagent/ # Parallel subagent manager with worktree isolation
│ ├── tui/ # Bubble Tea TUI — 29 screens, 5 themes
│ │ ├── commands/ # Slash command registry and built-in commands
│ │ ├── components/ # 40+ reusable TUI components
│ │ ├── layout/ # Responsive layout helpers
│ │ ├── streaming/ # Streaming response rendering and agent loop
│ │ ├── theme/ # Lipgloss theming (dark/light/auto/custom)
│ │ └── tuitypes/ # TUI-specific type definitions
│ ├── types/ # Core type definitions shared across all packages
│ └── workflow/ # Six-phase orchestration engine
│ └── prompts/ # Embedded markdown prompt templates
├── pkg/ # Public, importable packages
│ ├── arbitrage/ # Model scoring, cost estimation, recommendation
│ ├── autodream/ # Context consolidation (AutoDream compressor)
│ ├── bisect/ # Git bisect wrapper for finding offending commits
│ ├── history/ # Session history store
│ ├── keychain/ # OS keychain abstraction (Linux/macOS/Windows)
│ ├── ledger/ # Cross-session learning ledger (markdown-backed)
│ ├── rollback/ # Commit-chain manager (soft/hard/safe reset)
│ ├── session/ # Session lifecycle, persistence, checkpointing
│ └── taskrunner/ # Sequential and parallel task executor
├── scripts/ # Acceptance test suite (verify_v1.sh)
├── install.sh # One-liner installer script
├── Makefile # Build, test, lint, cross-compile, release targets
└── .goreleaser.yaml # Cross-compile and release configuration
cmd/m31a/main.go
├── internal/config (load TOML config)
├── internal/log (initialize structured logger)
├── pkg/keychain (OS keychain for API keys)
├── internal/provider (LLM provider registry)
├── pkg/session (session manager)
├── internal/tools (tool dispatcher)
│ └── internal/tools/subagent (subagent manager)
├── internal/git (git operations)
├── pkg/ledger (learning ledger)
├── pkg/rollback (commit rollback)
├── pkg/autodream (context consolidation)
└── internal/tui (Bubble Tea TUI)
├── internal/tui/commands (slash commands)
├── internal/tui/components (UI components)
├── internal/tui/theme (theming)
├── internal/tui/streaming (response streaming)
└── internal/workflow (phase orchestration)
Defined in internal/types/types.go:
| Type | Purpose |
|---|---|
WorkflowPhase |
Enum: idle, initialize, discuss, plan, execute, verify, ship |
TaskStatus |
Enum: pending, running, done, failed, skipped, unrecoverable |
RiskLevel |
Enum: safe, medium, dangerous, destructive |
ModelInfo |
Model metadata: ID, provider, pricing, context length, capabilities |
Message |
Chat message with role, content, segments, tool calls, usage |
ToolCall |
Structured tool invocation: ID, name, JSON input |
ToolResult |
Tool execution outcome: output, error, duration, truncation flag |
Tool |
Interface: Name, Description, RiskLevel, Execute |
SchemaProvider |
Optional interface for tools providing JSON Schema parameters |
Task |
Workflow task with ID, description, files, dependencies, acceptance criteria |
StreamChunk |
SSE stream delta: text, thinking duration, tool call fragments |
StreamIterator |
Cursor over streaming response with Next/Close functions |
Defined in internal/types/constants.go:
| Constant | Value | Purpose |
|---|---|---|
MaxFileSize |
5 MB | Maximum file read size |
MaxToolOutputChars |
10,000 | Maximum tool output characters |
MaxHealAttempts |
2 | Self-healing retry limit per task |
MaxPlanRetries |
3 | Plan generation retry limit |
MaxPlanRefinements |
5 | Plan refinement limit |
BashTimeout |
30 min | Maximum bash command duration |
BashOutputLimit |
50,000 | Maximum bash output characters |
MaxLLMResponseBytes |
1 MB | Maximum LLM response size |
MaxSessionFileSize |
50 MB | Maximum session file size (OOM protection) |
DefaultContextLength |
128,000 | Fallback context window size |
MaxToolsPerCall |
16 | Maximum tool calls per LLM response |
DefaultPermissionTimeout |
300s | Permission modal timeout |
ModelCacheTTL |
5 min | Model cache time-to-live |
DefaultMaxParallelTasks |
4 | Maximum concurrent task execution |
The Makefile provides these key targets:
| Target | Description |
|---|---|
make build |
Optimized binary with ldflags (version, commit, date) |
make debug |
Debug binary with symbols (-gcflags "all=-N -l") |
make test |
Race-enabled tests with coverage |
make lint |
golangci-lint with 5-minute timeout |
make check |
fmt + tidy + vet + test |
make cross |
Build for linux/darwin/windows x amd64/arm64 |
make release |
GoReleaser snapshot |
All binaries are compiled with CGO_ENABLED=0 for maximum portability. Version info is injected via ldflags at build time.
- No CGO -- Static binary, no dynamic library dependencies, trivial cross-compilation.
-
Bubble Tea TUI -- Elm-architecture with single-threaded
Update()loop, preventing race conditions in state mutations. -
Embedded prompts -- Workflow prompt templates are compiled into the binary via
//go:embed, eliminating runtime file dependencies. -
Project-local sessions -- Sessions live in
<project>/.m31a/instead of a global directory, keeping each project's state isolated. - Atomic writes -- All file writes use temp-file-then-rename to prevent corruption on crash.
-
Signal safety -- SIGTERM/SIGINT are routed through Bubble Tea's
Send()channel, respecting the single-threaded model.