48532de1cd
CI / helm (pull_request) Successful in 22s
CI / push-validation (pull_request) Successful in 26s
CI / typecheck (pull_request) Successful in 52s
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m20s
CI / e2e_tests (pull_request) Successful in 3m12s
CI / build (pull_request) Successful in 3m22s
CI / quality (pull_request) Successful in 3m42s
CI / security (pull_request) Successful in 4m15s
CI / integration_tests (pull_request) Successful in 8m53s
CI / unit_tests (pull_request) Successful in 8m58s
CI / docker (pull_request) Successful in 1m22s
CI / coverage (pull_request) Successful in 11m5s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (push) Waiting to run
CI / push-validation (push) Successful in 18s
CI / helm (push) Successful in 24s
CI / lint (push) Successful in 27s
CI / build (push) Successful in 33s
CI / security (push) Successful in 1m7s
CI / quality (push) Successful in 3m39s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Waiting to run
CI / integration_tests (push) Successful in 4m8s
CI / e2e_tests (push) Successful in 6m15s
CI / unit_tests (push) Successful in 8m10s
CI / docker (push) Successful in 10s
CI / coverage (push) Successful in 10m10s
CI / status-check (push) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 56m36s
- Add docs/modules/context-hydration.md: documents the ACMS context hydration pipeline (context_tier_hydrator) that fixes the empty ContextTierService bug (#1028). Covers hydrate_tiers_from_project, hydrate_tiers_for_plan, file listing strategies, limits, and fragment metadata. - Add docs/modules/git-worktree-sandbox.md: documents the GitWorktreeSandbox class that isolates plan apply changes in a dedicated git branch/worktree and merges back on commit (#4454). Covers full lifecycle, error types, branch naming, and fallback for non-git projects. - Update docs/architecture.md: add Git Worktree Sandbox Apply section and extend ACMS section with context hydration note. - Update mkdocs.yml: add both new module pages to the Modules nav. ISSUES CLOSED: #6841
371 lines
13 KiB
Markdown
371 lines
13 KiB
Markdown
# Architecture Overview
|
||
|
||
CleverAgents is a Python-first AI agent orchestration platform. It provides
|
||
a unified CLI (`agents`), an interactive TUI, an embedded runtime, and
|
||
service orchestration tools for building and running complex, long-running
|
||
AI-driven workflows.
|
||
|
||
This document gives a developer-oriented overview of the system. For the
|
||
authoritative specification see [`docs/specification.md`](specification.md).
|
||
For individual design decisions see the [ADR index](adr/index.md).
|
||
|
||
---
|
||
|
||
## High-Level Component Map
|
||
|
||
```mermaid
|
||
graph TD
|
||
subgraph "Entry Points"
|
||
CLI["CLI<br/>(agents / cleveragents)"]
|
||
TUI["TUI<br/>(agents tui)"]
|
||
SERVER["Server<br/>(agents server)"]
|
||
end
|
||
|
||
subgraph "Application Layer"
|
||
A2A["A2A Facade<br/>(local / HTTP)"]
|
||
DI["DI Container<br/>(application.container)"]
|
||
SERVICES["Application Services<br/>(plan, session, actor, skill, tool, …)"]
|
||
end
|
||
|
||
subgraph "Domain Layer"
|
||
PLAN["Plan Lifecycle<br/>(Strategize → Execute → Apply)"]
|
||
ACTOR["Actor System<br/>(config, loader, compiler)"]
|
||
RESOURCE["Resource DAG<br/>(handlers, inheritance)"]
|
||
DECISION["Decision Tree<br/>(record, version, rollback)"]
|
||
end
|
||
|
||
subgraph "Infrastructure Layer"
|
||
DB["Database<br/>(SQLAlchemy + Alembic)"]
|
||
SANDBOX["Sandbox<br/>(checkpoint, rollback)"]
|
||
OBS["Observability<br/>(logging, metrics, audit)"]
|
||
EVENTS["Event Bus<br/>(reactive streams)"]
|
||
PLUGINS["Plugin Manager"]
|
||
end
|
||
|
||
subgraph "Integration Layer"
|
||
LANGGRAPH["LangGraph Bridge"]
|
||
MCP["MCP Adapter"]
|
||
LSP["LSP Client"]
|
||
ACMS["ACMS<br/>(context management)"]
|
||
UKO["UKO Runtime<br/>(knowledge ontology)"]
|
||
end
|
||
|
||
CLI --> A2A
|
||
TUI --> A2A
|
||
SERVER --> A2A
|
||
A2A --> DI
|
||
DI --> SERVICES
|
||
SERVICES --> PLAN
|
||
SERVICES --> ACTOR
|
||
SERVICES --> RESOURCE
|
||
SERVICES --> DECISION
|
||
PLAN --> LANGGRAPH
|
||
ACTOR --> LANGGRAPH
|
||
LANGGRAPH --> MCP
|
||
LANGGRAPH --> LSP
|
||
SERVICES --> ACMS
|
||
ACMS --> UKO
|
||
SERVICES --> DB
|
||
SERVICES --> SANDBOX
|
||
SERVICES --> OBS
|
||
SERVICES --> EVENTS
|
||
SERVICES --> PLUGINS
|
||
```
|
||
|
||
---
|
||
|
||
## Layered Architecture
|
||
|
||
CleverAgents follows a strict layered architecture
|
||
([ADR-001](adr/ADR-001-layered-architecture.md)):
|
||
|
||
| Layer | Package | Responsibility |
|
||
|-------|---------|----------------|
|
||
| **Entry Points** | `cli`, `tui` | User-facing interfaces |
|
||
| **Application** | `application` | DI wiring, service orchestration |
|
||
| **Domain** | `domain`, `actor`, `skills`, `tool`, `resource` | Business logic |
|
||
| **Infrastructure** | `infrastructure` | Database, sandbox, events, observability |
|
||
| **Integration** | `a2a`, `mcp`, `lsp`, `langgraph`, `acms` | External protocol adapters |
|
||
| **Core** | `core`, `shared`, `config` | Cross-cutting utilities |
|
||
|
||
Dependencies flow **downward only** — upper layers may import from lower
|
||
layers but never the reverse.
|
||
|
||
---
|
||
|
||
## Plan Lifecycle
|
||
|
||
The plan lifecycle is the central abstraction
|
||
([ADR-006](adr/ADR-006-plan-lifecycle.md)):
|
||
|
||
```
|
||
Action ──► Strategize ──► Execute ──► Apply
|
||
│ │ │ │
|
||
│ (estimate) (validate) (diff review)
|
||
│ │
|
||
└───────────────────────────┘
|
||
(correction / rollback)
|
||
```
|
||
|
||
| Phase | Description |
|
||
|-------|-------------|
|
||
| **Action** | User intent captured as a plan request |
|
||
| **Strategize** | LLM generates a structured plan with operations |
|
||
| **Execute** | Operations executed against resources via tools |
|
||
| **Apply** | Validated changes committed; diff reviewed and approved |
|
||
|
||
Phase transitions are gated by:
|
||
- **Validation pipeline** — rule-based checks with severity levels
|
||
- **Definition-of-Done** — explicit criteria evaluated before Apply
|
||
- **Advisory locking** — prevents concurrent modification of the same plan
|
||
- **Invariant reconciliation** — `InvariantReconciliationActor` runs automatically
|
||
at each phase transition (`start_strategize`, `execute_plan`, `apply_plan`);
|
||
failures raise `ReconciliationBlockedError` and emit `INVARIANT_VIOLATED` events,
|
||
blocking the transition until invariants are satisfied
|
||
|
||
---
|
||
|
||
## Actor System
|
||
|
||
Actors are the execution units ([ADR-010](adr/ADR-010-actor-and-agent-architecture.md),
|
||
[ADR-031](adr/ADR-031-actor-abstraction-definition.md)):
|
||
|
||
- Defined in YAML with a LangGraph node graph
|
||
- Each node binds an LLM, a set of tools, and optional LSP/MCP sources
|
||
- Compiled by `ActorCompiler` into a runnable `CompiledActor`
|
||
- Registered in `ActorRegistry` and resolved by name at runtime
|
||
|
||
```yaml
|
||
# examples/actors/graph_workflow.yaml
|
||
name: openai/gpt-4o
|
||
entry_node: planner
|
||
nodes:
|
||
planner:
|
||
model: gpt-4o
|
||
tool_sources: [builtin, mcp://bash-tools]
|
||
executor:
|
||
model: gpt-4o-mini
|
||
tool_sources: [builtin]
|
||
edges:
|
||
- from: planner
|
||
to: executor
|
||
condition: needs_execution
|
||
```
|
||
|
||
---
|
||
|
||
## Tool System
|
||
|
||
Tools are the atomic capabilities available to actors
|
||
([ADR-011](adr/ADR-011-tool-system.md)):
|
||
|
||
- Registered in `ToolRegistry` with a `ToolSpec` (JSON Schema) and executor
|
||
- Four-stage lifecycle: **activate → validate → execute → deactivate**
|
||
- Sources: `builtin`, `mcp`, `lsp`, `skill`
|
||
- Safety profiles control sandbox requirements, human approval gates, and cost limits
|
||
- Read-only enforcement blocks write-capable tools on read-only plans
|
||
|
||
---
|
||
|
||
## Skill System
|
||
|
||
Skills are composable capability bundles
|
||
([ADR-012](adr/ADR-012-skill-system.md),
|
||
[ADR-028](adr/ADR-028-agent-skills-standard.md)):
|
||
|
||
- Loaded from YAML or AgentSkills.io-compatible directories
|
||
- Three-tier progressive disclosure: **discover → activate → deactivate**
|
||
- Each skill exposes one or more tools to the actor
|
||
- `SkillRegistry` tracks all registered skills; `SkillRefreshResult` reports changes
|
||
|
||
---
|
||
|
||
## Resource System
|
||
|
||
Resources are managed external entities
|
||
([ADR-008](adr/ADR-008-resource-system.md)):
|
||
|
||
- Organized as a DAG (Directed Acyclic Graph) with dependency tracking
|
||
- Type hierarchy with multiple inheritance and field merging
|
||
([ADR-042](adr/ADR-042-resource-type-inheritance.md))
|
||
- Built-in types: `file`, `directory`, `sqlite`, `postgresql`, `mysql`,
|
||
`duckdb`, `container.docker`, `container.podman`, `lsp.*`, `cloud.*`
|
||
- Each type has a handler implementing CRUD, checkpoint, and rollback
|
||
|
||
---
|
||
|
||
## Context Management (ACMS)
|
||
|
||
The Advanced Context Management System manages what context is sent to the
|
||
LLM at each phase ([ADR-014](adr/ADR-014-context-management-acms.md)):
|
||
|
||
- **Tier 1** — Always-present system context
|
||
- **Tier 2** — Phase-specific context (plan, project, actor)
|
||
- **Tier 3** — Dynamic retrieval (semantic search, UKO inference)
|
||
|
||
The **UKO Runtime** (Universal Knowledge Ontology) provides graph-based
|
||
knowledge inference and persistence for Tier 3 context strategies.
|
||
|
||
Key UKO capabilities:
|
||
|
||
- **Typed triples with provenance** — every triple carries `sourceResource`,
|
||
`validFrom`, and `isCurrent` metadata
|
||
- **Temporal versioning** — a revision chain tracks ontology state across
|
||
indexing runs, enabling point-in-time queries
|
||
- **Implicit inference** — `UKOInferenceEngine` produces `uko:implicitSiblingOf`,
|
||
`uko:implicitContains`, and `uko:implicitDependsOn` triples with confidence 0.7
|
||
- **Graph persistence** — `UKOGraphPersistence` serialises/restores state via
|
||
JSON-file or in-memory backends across application restarts
|
||
|
||
**Context hydration** bridges the resource registry and the ACMS tier service.
|
||
`context_tier_hydrator.hydrate_tiers_for_plan()` reads files from all
|
||
resources linked to the active project and stores them as `TieredFragment`
|
||
objects in `ContextTierService` before context assembly begins. Without
|
||
hydration, the LLM receives zero file context. See
|
||
[ACMS Context Hydration](modules/context-hydration.md) for details.
|
||
|
||
---
|
||
|
||
## Invariant Reconciliation
|
||
|
||
The **Invariant Reconciliation Actor** (`builtin/invariant-reconciliation`)
|
||
is automatically invoked at the start of the Strategize, Execute, and Apply
|
||
phase transitions by `PlanLifecycleService`.
|
||
|
||
**Reconciliation algorithm** (spec §19440–19600):
|
||
|
||
1. Collect invariants from four scopes: global, project, action, plan.
|
||
2. Group by normalised text (case-insensitive, stripped).
|
||
3. Detect conflicts between invariants at different scopes.
|
||
4. Resolve using specificity: `plan > action > project > global`.
|
||
Exception: `non_overridable` global invariants always win.
|
||
5. Record an `invariant_enforced` decision for each active invariant.
|
||
6. Return a reconciled `InvariantSet`.
|
||
|
||
**Failure behaviour:**
|
||
|
||
- Reconciliation failures block the phase transition with
|
||
`ReconciliationBlockedError` and emit an `INVARIANT_VIOLATED` event.
|
||
- Post-correction reconciliation runs via `CORRECTION_APPLIED` event
|
||
subscription (best-effort; does not block correction completion).
|
||
|
||
**DI registration:** `InvariantService` is registered as a Singleton
|
||
provider in the DI container.
|
||
|
||
```python
|
||
from cleveragents.actor.reconciliation import InvariantReconciliationActor
|
||
|
||
actor = InvariantReconciliationActor(
|
||
invariant_service=container.invariant_service(),
|
||
decision_service=container.decision_service(),
|
||
)
|
||
result = actor.run(plan_id="...", project_name="...", action_name="...")
|
||
# result.reconciled_set — effective InvariantSet
|
||
# result.conflicts — list[ConflictRecord] with resolution details
|
||
```
|
||
|
||
---
|
||
|
||
## Git Worktree Sandbox Apply
|
||
|
||
When `plan apply` commits changes to a git-checkout resource, the changes
|
||
are isolated in a dedicated git branch and worktree rather than written
|
||
directly to the working tree.
|
||
|
||
**Flow:**
|
||
|
||
1. `PlanLifecycleService` detects a git-checkout resource and creates a
|
||
`GitWorktreeSandbox`.
|
||
2. A new branch `cleveragents/plan-<plan_id>` is created from the current HEAD.
|
||
3. A temporary worktree is created at a system temp directory.
|
||
4. The actor writes changes inside the worktree.
|
||
5. On approval: changes are staged, committed in the worktree, then merged
|
||
back to the original branch via `git merge`.
|
||
6. On rejection: the worktree is discarded and the original branch is
|
||
untouched.
|
||
|
||
Non-git projects fall back to the original flat file copy strategy.
|
||
|
||
See [Git Worktree Sandbox](modules/git-worktree-sandbox.md) for the full
|
||
API reference.
|
||
|
||
---
|
||
|
||
## A2A Protocol Boundary
|
||
|
||
All CLI, TUI, and server interactions cross the A2A boundary
|
||
([ADR-026](adr/ADR-026-agent-client-protocol.md),
|
||
[ADR-047](adr/ADR-047-acp-standard-adoption.md)):
|
||
|
||
- **Local mode** — `A2aLocalFacade` maps operations to direct Python calls
|
||
- **Server mode** — `A2aHttpTransport` (stub; full implementation pending)
|
||
- Version negotiation via `A2aVersionNegotiator`
|
||
|
||
---
|
||
|
||
## MCP Integration
|
||
|
||
External tool servers are integrated via the Model Context Protocol
|
||
([ADR-029](adr/ADR-029-model-context-protocol.md)):
|
||
|
||
- `MCPToolAdapter` manages server lifecycle and tool discovery
|
||
- `McpClient` provides lazy start and auto-stop
|
||
- `SandboxPathRewriter` prevents path traversal
|
||
- `MCPRefreshHook` keeps skill registrations in sync with server changes
|
||
|
||
---
|
||
|
||
## LSP Integration
|
||
|
||
Language Server Protocol servers provide code intelligence tools
|
||
([ADR-027](adr/ADR-027-language-server-protocol.md)):
|
||
|
||
- `LSPClient` manages server lifecycle and capability negotiation
|
||
- LSP tools are registered in `ToolRegistry` with `source="lsp"`
|
||
- Per-node LSP bindings in actor YAML control which server each node uses
|
||
|
||
---
|
||
|
||
## Dependency Injection
|
||
|
||
All application services are wired via the DI container
|
||
([ADR-003](adr/ADR-003-dependency-injection.md)):
|
||
|
||
```python
|
||
from cleveragents.application.container import Container
|
||
|
||
container = Container()
|
||
plan_service = container.plan_service()
|
||
session_service = container.session_service()
|
||
```
|
||
|
||
The container is the single source of truth for service instantiation.
|
||
Never construct services directly in application code.
|
||
|
||
---
|
||
|
||
## Observability
|
||
|
||
([ADR-025](adr/ADR-025-observability-and-logging.md))
|
||
|
||
- Structured logging via `cleveragents.config.logging`
|
||
- Metrics processing via `cleveragents.config.metrics_processor`
|
||
- Audit logging via `infrastructure.observability`
|
||
- Token/cost tracking per plan and per day with budget enforcement
|
||
|
||
---
|
||
|
||
## Key Design Decisions
|
||
|
||
| Decision | ADR | Summary |
|
||
|----------|-----|---------|
|
||
| Layered architecture | [ADR-001](adr/ADR-001-layered-architecture.md) | Strict layer boundaries, no upward imports |
|
||
| Namespace system | [ADR-002](adr/ADR-002-namespace-system.md) | `provider/name` qualified identifiers |
|
||
| Dependency injection | [ADR-003](adr/ADR-003-dependency-injection.md) | Single DI container, no service locator |
|
||
| Plan lifecycle | [ADR-006](adr/ADR-006-plan-lifecycle.md) | Four-phase lifecycle with gating |
|
||
| LangGraph integration | [ADR-022](adr/ADR-022-langchain-langgraph-integration.md) | LangGraph as graph execution engine |
|
||
| Sandboxing | [ADR-015](adr/ADR-015-sandbox-and-checkpoint.md) | Checkpoint/rollback for all resource writes |
|
||
| Template security | [ADR-032](adr/ADR-032-jinja2-yaml-template-preprocessing.md) | Sandboxed Jinja2 with allowlist |
|
||
| TUI framework | [ADR-044](adr/ADR-044-tui-architecture-and-framework.md) | Textual-based full-screen TUI with first-run experience, persona system, session export/import |
|
||
| Server architecture | [ADR-048](adr/ADR-048-server-application-architecture.md) | ASGI server with Kubernetes deployment |
|