Skip to content

Commit 4afef6f

Browse files
committed
docs: add architecture.md
1 parent d34bbd5 commit 4afef6f

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Architecture
2+
3+
## Overview
4+
5+
Agent Chat CLI is a Python TUI application built with Textual that provides an interactive chat interface for Claude AI with MCP (Model Context Protocol) server support.
6+
7+
## Directory Structure
8+
9+
```
10+
src/agent_chat_cli/
11+
├── app.py # Main application entry point
12+
├── components/ # UI components (Textual widgets)
13+
│ ├── chat_history.py # Container for chat messages
14+
│ ├── messages.py # Message widgets and UI Message type
15+
│ ├── user_input.py # User input component
16+
│ ├── thinking_indicator.py # Loading indicator
17+
│ └── header.py # App header with config info
18+
├── utils/ # Business logic and utilities
19+
│ ├── agent_loop.py # Claude SDK conversation loop
20+
│ ├── message_bus.py # Routes messages between agent and UI
21+
│ ├── config.py # Configuration loading and validation
22+
│ ├── enums.py # All enum types
23+
│ ├── system_prompt.py # System prompt assembly
24+
│ ├── format_tool_input.py # Tool input formatting
25+
│ └── tool_info.py # MCP tool name parsing
26+
└── utils/styles.tcss # Textual CSS styles
27+
```
28+
29+
## Core Components
30+
31+
### App Layer (`app.py`)
32+
Main Textual application that initializes and coordinates all components.
33+
34+
### Components Layer
35+
Textual widgets responsible for UI rendering:
36+
- **ChatHistory**: Container that displays message widgets
37+
- **Message widgets**: SystemMessage, UserMessage, AgentMessage, ToolMessage
38+
- **UserInput**: Handles user text input and submission
39+
- **ThinkingIndicator**: Shows when agent is processing
40+
41+
### Utils Layer
42+
43+
#### Agent Loop (`agent_loop.py`)
44+
Manages the conversation loop with Claude SDK:
45+
- Maintains async queue for user queries
46+
- Handles streaming responses
47+
- Parses SDK messages into structured AgentMessage objects
48+
- Emits AgentMessageType events (STREAM_EVENT, ASSISTANT, RESULT)
49+
50+
#### Message Bus (`message_bus.py`)
51+
Routes agent messages to appropriate UI components:
52+
- Handles streaming text updates
53+
- Mounts tool use messages
54+
- Controls thinking indicator state
55+
- Manages scroll-to-bottom behavior
56+
57+
#### Config (`config.py`)
58+
Loads and validates YAML configuration:
59+
- Filters disabled MCP servers
60+
- Loads prompts from files
61+
- Expands environment variables
62+
- Combines system prompt with MCP server prompts
63+
64+
## Data Flow
65+
66+
```
67+
User Input
68+
69+
UserInput.on_input_submitted
70+
71+
MessagePosted event → ChatHistory (immediate UI update)
72+
73+
AgentLoop.query (added to queue)
74+
75+
Claude SDK (streaming response)
76+
77+
AgentLoop._handle_message
78+
79+
AgentMessage (typed message) → MessageBus.handle_agent_message
80+
81+
Match on AgentMessageType:
82+
- STREAM_EVENT → Update streaming message widget
83+
- ASSISTANT → Mount tool use widgets
84+
- RESULT → Reset thinking indicator
85+
```
86+
87+
## Key Types
88+
89+
### Enums (`utils/enums.py`)
90+
91+
**AgentMessageType**: Agent communication events
92+
- ASSISTANT: Assistant message with content blocks
93+
- STREAM_EVENT: Streaming text chunk
94+
- RESULT: Response complete
95+
- INIT, SYSTEM: Initialization and system events
96+
97+
**ContentType**: Content block types
98+
- TEXT: Text content
99+
- TOOL_USE: Tool call
100+
- CONTENT_BLOCK_DELTA: SDK streaming event type
101+
- TEXT_DELTA: SDK text delta type
102+
103+
**MessageType** (`components/messages.py`): UI message types
104+
- SYSTEM, USER, AGENT, TOOL
105+
106+
### Data Classes
107+
108+
**AgentMessage** (`utils/agent_loop.py`): Structured message from agent loop
109+
```python
110+
@dataclass
111+
class AgentMessage:
112+
type: AgentMessageType
113+
data: Any
114+
```
115+
116+
**Message** (`components/messages.py`): UI message data
117+
```python
118+
@dataclass
119+
class Message:
120+
type: MessageType
121+
content: str
122+
metadata: dict[str, Any] | None = None
123+
```
124+
125+
## Configuration System
126+
127+
Configuration is loaded from `agent-chat-cli.config.yaml`:
128+
- **system_prompt**: Base system prompt (supports file paths)
129+
- **model**: Claude model to use
130+
- **include_partial_messages**: Enable streaming
131+
- **mcp_servers**: MCP server configurations (filtered by enabled flag)
132+
- **agents**: Named agent configurations
133+
- **disallowed_tools**: Tool filtering
134+
- **permission_mode**: Permission handling mode
135+
136+
MCP server prompts are automatically appended to the system prompt.
137+
138+
## Event Flow
139+
140+
### User Message Flow
141+
1. User submits text → UserInput
142+
2. MessagePosted event → App
143+
3. App → MessageBus.on_message_posted
144+
4. MessageBus → ChatHistory.add_message
145+
5. MessageBus → Scroll to bottom
146+
147+
### Agent Response Flow
148+
1. AgentLoop receives SDK message
149+
2. Parse into AgentMessage with AgentMessageType
150+
3. MessageBus.handle_agent_message (match/case on type)
151+
4. Update UI components based on type
152+
5. Scroll to bottom
153+
154+
## Notes
155+
156+
- Two distinct MessageType enums exist for different purposes (UI vs Agent events)
157+
- Message bus manages stateful streaming (tracks current_agent_message)
158+
- Config loading combines multiple prompts into final system_prompt
159+
- Tool names follow format: `mcp__servername__toolname`

0 commit comments

Comments
 (0)