A local-first, component-based AI Agent state management system designed for modularity, cost-efficiency, and observability. Inspired by the robust design principles of advanced AI agents, LocalAgent provides a solid foundation for building intelligent, stateful applications.
Table of Contents
- Features
- Architecture Overview
- Core Concepts
- Economic Considerations
- Observability & Debugging
- Getting Started
- Project Structure
- Contributing
- License
Features
- Component System: Modular and extensible components (WorkingHistory, Memory, Todo, SubAgent) with isolated state management.
- Local-first Persistence: Automatic state serialization to local JSON files, ensuring data persistence and low latency.
- Context Management: Intelligent prompt assembly with budget-aware truncation and dynamic model selection for cost-efficiency.
- Observability: Event-driven architecture for real-time monitoring, debugging, and state snapshots.
- Real-world Tooling: Integration with external tools (e.g., File I/O, Weather API) for practical agent capabilities.
- Interactive CLI: Enhanced command-line interface with typewriter effects, spinners, and colored logs for a rich user experience.
Architecture Overview
The LocalAgent Framework is built around a central Agent Orchestrator (LocalAgent) that manages the agent's lifecycle, state, and execution loop. It leverages a Component System for modularity, a StateManager for persistent state, and an EventBus for decoupled communication. Interactions with Large Language Models (LLMs) are handled via an LLMProvider, and external capabilities are exposed through a ToolRegistry.
graph TD
subgraph Agent Core [The Execution Loop]
A[User Input / External Event] --> B(Agent Orchestrator)
B --> C{Context Assembly}
C --> D[LLM Call]
D --> E{LLM Response}
E --> F(Tool Execution)
F --> G{State Update}
G --> H(Event Bus: StateChange)
H --> I(Observability / Debugger)
G --> B
end
subgraph Components [State Providers]
J[WorkingHistory]
K[Memory]
L[Todo]
M[SubAgent]
end
subgraph State & Context Management
N[Local Storage]
O[Context Manager]
P[Model Router]
end
subgraph Observability
Q[Snapshot / Debugger]
end
style B fill:#f9f,stroke:#333,stroke-width:2px
style C fill:#ccf,stroke:#333,stroke-width:2px
style D fill:#afa,stroke:#333,stroke-width:2px
style E fill:#ccf,stroke:#333,stroke-width:2px
style F fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#ccf,stroke:#333,stroke-width:2px
style H fill:#ffc,stroke:#333,stroke-width:2px
style I fill:#ffc,stroke:#333,stroke-width:2px
style Q fill:#ffc,stroke:#333,stroke-width:2px
B -- manages --> J
B -- manages --> K
B -- manages --> L
B -- manages --> M
C -- queries --> J
C -- queries --> K
C -- queries --> L
C -- queries --> M
C -- uses --> O
C -- consults --> P
D -- calls --> LLMProvider
E -- contains --> ToolCalls
F -- uses --> ToolRegistry
G -- updates --> N
H -- notifies --> Q
N -- stores --> AgentState
O -- builds --> Prompt
P -- selects --> LLMModel
ToolRegistry -- executes --> ExternalTools
Core Concepts
Agent Lifecycle
The agent follows a well-defined lifecycle to ensure predictable and recoverable execution:
| State (Enum) | Description | Transition Triggers |
|---|---|---|
| INITIALIZED | Configuration loaded, components registered, but task not yet started. | agent.start(task) |
| RUNNING | Main execution loop is active (Context -> LLM -> Action -> State Update). | LLM response, tool execution completion. |
| PAUSED | Execution temporarily halted, state serialized to local disk. | agent.pause(), system interruption (e.g., user input needed). |
| RESUMED | State reloaded from disk, execution loop restarted. | agent.resume() |
| COMPLETED | Task objective achieved. | LLM signals completion. |
| FAILED | An unrecoverable error occurred. | Tool execution failure, LLM call error. |
Component System
Components are the building blocks of the agent's intelligence. The framework adopts a component-based architecture for low coupling and high extensibility.
- Component Interface: All components must implement the
IComponentinterface, defining core methods likeinitialize(),getState(),updateState(), andrenderPromptFragment(). - Dependency Management: Components can declare their dependencies (e.g.,
static dependencies = ['Memory', 'WorkingHistory']). TheLocalAgentensures dependencies are initialized in the correct order. - State Isolation: Each component manages its own state slice, which is part of the overall agent state.
State Management
The StateManager is responsible for centralizing and persisting the agent's state.
- Local-first Persistence: The entire agent state, including all component states, is automatically serialized to local JSON files, ensuring data integrity and allowing for session recovery.
- Snapshots: The
StateManagersupports taking snapshots of the current state, enabling time-travel debugging and easy restoration to previous points.
Event Bus
The EventBus (an EventEmitter instance) is the primary mechanism for asynchronous, decoupled communication between components and the observability layer. Key events include agent:state_change, component:state_updated, llm:call_start, tool:execution_end, etc. This design promotes loose coupling and simplifies maintenance.
Economic Considerations
The framework is designed to balance performance (effectiveness) with cost (economy).
Context Compression & Smart Truncation
The ContextManager implements a multi-layered strategy:
- Priority-based Truncation: When the prompt size approaches the token limit, the manager truncates content based on a predefined priority order:
- Lowest Priority: Oldest tool outputs, verbose logs.
- Medium Priority: Older
WorkingHistorymessages. - Highest Priority: System prompt,
Todolist, andMemorysummaries (never truncated).
- History Summarization: The
Memorycomponent actively monitors theWorkingHistory's token count. When it exceeds a threshold (e.g., 50% of the total budget), it triggers a weaker model to summarize the older half of the history, replacing raw messages with a concisesummarystring.
Model Selection Strategy
A ModelRouter dynamically selects the appropriate LLM based on the task and current state:
| Task Type | Model Choice | Rationale |
|---|---|---|
| Core Reasoning (Planning, Tool Selection) | Strong Model (e.g., GPT-4o, Claude 3.5 Sonnet) | Requires high-level reasoning and complex instruction following. |
| Summarization (History, Tool Output) | Weak Model (e.g., GPT-3.5, Claude 3 Haiku) | Simple text-to-text transformation; highly cost-effective. |
| State Validation (e.g., checking task completion) | Weak Model | Low complexity, high-frequency checks. |
| Code Generation/Refactoring | Strong Model (or specialized code model) | Requires high fidelity and correctness. |
Observability & Debugging
The framework is designed with full observability in mind, crucial for debugging complex agent behaviors.
- Event System: The global
EventBusbroadcasts events for every significant operation, allowing external listeners (e.g., UI, logging services, debuggers) to subscribe without coupling to the agent's core logic. - Step-by-step Execution: The
LocalAgentcan be configured to pause after each LLM turn, allowing developers to inspect the state before proceeding. - State Snapshots: The
StateManager'stakeSnapshot()method serializes the entire state to a JSON file, enabling time-travel debugging by loading snapshots and resuming execution from that precise point.
Getting Started
Configuration
- Copy
.env.exampleto.env. - Fill in your
OPENAI_API_KEYand other optional settings. Note: If no API key is provided, the framework will run in Mock Mode for demonstration.
Installation
Running Examples
- Main Demo: Runs a basic agent interaction.
bun start
- **Document Analysis Example**: Agent reads a local file, summarizes its content, and adds key facts to memory.
```bash
bun example:doc
- Weather Report Example: Agent checks weather for a city and provides personalized suggestions based on user preferences in memory.
bun example:weather
## Project Structure
- `src/core.ts`: Defines core interfaces (`IComponent`, `AgentState`), `StateManager`, and `EventBus`.
- `src/agent.ts`: The `LocalAgent` Orchestrator, managing the execution loop, component registration, and tool invocation.
- `src/components.ts`: Implementations of built-in components like `WorkingHistory`, `TodoComponent`, `MemoryComponent`, and `SubAgent`.
- `src/llm.ts`: `LLMProvider` for abstracting LLM interactions, supporting real API calls and mock responses.
- `src/tools.ts`: `ToolRegistry` and implementations of `FileReadTool` and `WeatherTool`.
- `src/ui.ts`: Utility for enhanced CLI output (typewriter effects, spinners, colors).
- `src/index.ts`: Main entry point for the basic demo.
- `src/example_doc_analysis.ts`: Example demonstrating document analysis with `FileReadTool`.
- `src/example_weather.ts`: Example demonstrating weather inquiry with `WeatherTool`.
- `data/`: Directory for persistent agent state and live status dashboards.
## Contributing
Contributions are welcome! Please feel free to open issues or submit pull requests.
## License
This project is licensed under the MIT License.