Tutorial: Building a Chat Assistant
Relevant source files
The following files were used as context for generating this wiki page:The Chat Assistant is the Minimum Viable Product (MVP) application for the Loom project. Its primary purpose is to validate the core architectural principle of "Brain/Hand Separation," where the agent's reasoning (the "Brain") is handled in Python for rapid iteration, and tool execution (the "Hands") is managed by the secure Rust Core. This application serves as a foundational example of a cognitive agent capable of tool use, web search, and file system operations within the Loom runtime.
The Chat Assistant is the first step in a planned progression of applications, leading to more complex systems like a Market Analyst and a full Desktop Assistant. It demonstrates the fundamental capabilities of the Loom runtime, including direct LLM calls and tool usage via the Rust bridge.
Sources: ROADMAP.md:5-18, 33-36, README.md:52-60
Architecture Overview
The Loom project is built on a "Brain/Hand Separation" architecture, which divides responsibilities between a flexible Python "Brain" for cognitive tasks and a stable Rust "Hands" for infrastructure and tool execution.
┌─────────────────────────────────────────────────────────────────────┐
│ Python (Brain 🧠) Rust Core (Hands 🤚) │
│ ════════════════ ══════════════════ │
│ • LLM calls (direct HTTP) • Event Bus │
│ • Cognitive Loop (ReAct/CoT) • Tool Registry + Sandbox │
│ • Context Engineering • Agent Lifecycle │
│ • Memory strategies • Persistent Store │
│ • Business logic • System Integration │
│ • MCP Proxy │
│ Fast iteration needed Stable infrastructure │
└─────────────────────────────────────────────────────────────────────┘
Sources: ROADMAP.md:20-31
The Chat Assistant is a direct implementation of this model. A user interacts with the assistant via the loom chat command-line interface. This command starts a Python-based CognitiveAgent which runs a reasoning loop. When the agent decides to use a tool, it communicates with the Rust Core to execute it securely.
The following diagram illustrates the data flow for the Chat Assistant.
Configuration (loom.toml)
The behavior of the Chat Assistant is defined in apps/chat-assistant/loom.toml. This file configures the LLM provider, agent properties, and available tools.
Sources: apps/chat-assistant/loom.toml
LLM Provider
The [llm.deepseek] section configures the connection to the DeepSeek LLM API.
| Parameter | Description | Value |
|---|---|---|
type | The type of LLM provider. | "http" |
api_key | The API key for authentication, loaded from an environment variable. | "${DEEPSEEK_API_KEY}" |
api_base | The base URL for the LLM API endpoint. | "https://api.deepseek.com" |
model | The specific model to use for chat completions. | "deepseek-chat" |
max_tokens | The maximum number of tokens to generate in a response. | 4096 |
temperature | The sampling temperature for generation, controlling randomness. | 0.7 |
Sources: apps/chat-assistant/loom.toml:2-8
Agent Configuration
The [agent.chat-assistant] section defines the core properties of the cognitive agent.
| Parameter | Description | Value |
|---|---|---|
system_prompt | The initial instruction given to the LLM to set its persona and goals. | "You are a helpful assistant..." |
available_tools | A list of tools the agent is permitted to use. | ["web:search", "fs:read_file", ...] |
max_iterations | The maximum number of steps in the ReAct (Thought-Action-Observation) loop. | 15 |
thinking_strategy | The reasoning pattern the agent should follow. | "react" |
Sources: apps/chat-assistant/loom.toml:10-20
The Cognitive Agent (chatting.py)
The heart of the Chat Assistant is the CognitiveAgent, defined in apps/chat-assistant/agents/chatting.py. This agent is responsible for managing the "perceive-think-act" loop. It takes the user's goal, reasons about it using an LLM, executes tools, and generates a final answer.
The agent is configured with the react thinking strategy, which is an iterative process of Thought, Action, and Observation.
Sources: apps/chat-assistant/agents/chatting.py:1-17, loom-py/src/loom/cognitive/README.md:33-49, 90-92
ReAct Loop
The ReAct (Reasoning and Acting) strategy follows a cycle:
- Thought: The LLM reasons about the goal and decides on the next step.
- Action: The LLM chooses a tool and its arguments to execute.
- Observation: The agent executes the tool via the Rust Core and receives a result.
This cycle repeats until the agent has enough information to provide a final answer.
The diagram below shows the ReAct cognitive loop.
Launching and Interaction (loom chat)
The Chat Assistant is launched from the command line using the loom CLI.
# Start an interactive chat with the cognitive agent
loom chat
# Specify a different model
loom chat --model deepseek
Sources: loom-py/src/loom/cli/README.md:46-52
Once in the chat session, you can use several interactive commands to manage the conversation.
| Command | Description |
|---|---|
/clear | Clear the conversation history. |
/stats | Show session statistics. |
/exit | Exit the chat session. |
Sources: loom-py/src/loom/cli/README.md:81-85
User Interface and Streaming
The chat interface is rendered in the terminal using rich text formatting to distinguish between different types of messages. This provides a clear view of the agent's thought process.
Sources: loom-py/src/loom/cli/README.md:92-98
UI Components
The UI is composed of several distinct visual elements, each printed by a specific function.
print_user_message(): Displays the user's input.print_thinking_header(): Indicates the agent is starting its reasoning process.print_thinking_step(): Shows each step of the ReAct loop, including the tool name, arguments, and result.print_assistant_message(): Displays the final answer from the agent, with markdown rendering.print_error()/print_success(): Show status messages.
Sources: loom-py/tests/unit/test_cli_ui.py:50-141
Streaming Protocol
To provide real-time feedback, the agent uses a gRPC-based streaming protocol. When a user sends a message, the backend agent sends back a series of StreamChunk messages as it thinks and generates the response, followed by a final StreamComplete message.
This sequence diagram shows the streaming communication flow.
The StreamChunk message contains the content, a sequence number, and a StreamContentType enum that tells the client how to display the information (e.g., as a thought, a tool call, or regular text).
Sources: loom-proto/proto/streaming.proto:20-37
Conclusion
The Chat Assistant is a powerful yet simple demonstration of the Loom runtime's core capabilities. It effectively validates the "Brain/Hand Separation" architecture by combining a flexible Python-based cognitive loop with the security and performance of the Rust Core for tool execution. By building upon this foundation, developers can create more sophisticated, long-running, and collaborative multi-agent systems as envisioned in the project's roadmap.
Sources: ROADMAP.md:5-9, 33-39