The Agent System provides the core abstraction for building intelligent LLM-powered applications within AStack. Agents orchestrate interactions between language models (via ModelProvider), external tools, and conversation memory to enable autonomous task execution with reasoning capabilities.
This document provides an architectural overview of the Agent system. For detailed implementation information, refer to:
For the model provider abstraction that agents depend on, see Model Provider Interface.
An Agent is an AStack Component that wraps a language model with additional capabilities:
Agents implement the ReAct (Reasoning + Acting) pattern, where the model alternates between reasoning about the task and taking actions through tools until it reaches a conclusion.
| Component | Purpose | Package |
|---|---|---|
Agent | Base agent implementation with synchronous execution | @astack-tech/components |
StreamingAgent | Agent variant with real-time progress updates | @astack-tech/components |
ModelProvider | Interface for LLM integration | @astack-tech/integrations |
Memory | Interface for conversation context storage | @astack-tech/components |
Tool | Interface for external capabilities | @astack-tech/tools |
The following diagram shows how the Agent system integrates with AStack's core architecture and relates to other framework components.
Sources:
The Agent system is built around several key TypeScript interfaces that define contracts between components:
Defines the format for all communication within the agent system. Supports multiple roles (system, user, assistant, tool) and includes fields for tool interactions.
Sources: packages/components/src/agents/index.ts6-38
Abstracts language model interactions. Agents call chatCompletion() to get responses from the LLM.
The temporaryTools option allows passing tool definitions on a per-request basis. See Model Provider Interface for details.
Sources: packages/components/src/agents/index.ts162-184
Minimal interface for external capabilities. Tools must provide identification, description, and parameter schema.
Tools must implement either execute(args) or invoke(args) methods. See Tool Integration for details.
Sources: packages/components/src/agents/index.ts43-58
Manages conversation history and context. The default implementation (DefaultMemory) stores all messages in memory.
See Memory Management for implementation details and custom memory patterns.
Sources: packages/components/src/agents/index.ts63-127
Configuration object passed to Agent constructor:
| Field | Type | Default | Description |
|---|---|---|---|
model | ModelProvider | required | LLM provider instance |
tools | Tool[] | [] | Available tools for agent |
systemPrompt | string | "你是一个智能助手" | System message |
memory | Memory | DefaultMemory | Memory implementation |
maxIterations | number | 10 | Maximum tool execution rounds |
verbose | boolean | false | Enable debug logging |
supportsToolCalls | boolean | true | Enable tool calling |
Sources: packages/components/src/agents/index.ts233-268
AgentInput - Passed to agent.run():
AgentOutput - Returned from agent.run():
Sources: packages/components/src/agents/index.ts189-228
Agents implement a multi-turn execution loop that allows the language model to iteratively use tools and refine its response. The flow is managed by the Agent.run() method and delegated to the internal executeWithTools() method.
High-Level Flow Diagram:
Sources:
The Agent implements the ReAct (Reasoning + Acting) pattern through an iterative loop. In each iteration:
This enables complex multi-step task execution where the agent can gather information incrementally.
Example Multi-Turn Execution:
For detailed implementation of the execution loop, including error handling and tool invocation logic, see Base Agent.
Sources:
AStack provides two agent implementations: the standard Agent class for synchronous execution, and StreamingAgent for real-time progress updates.
The base Agent class in packages/components/src/agents/index.ts273-638 provides synchronous execution with complete results returned after all iterations complete.
Core Methods:
| Method | Signature | Description |
|---|---|---|
constructor() | (config: AgentConfig) | Initialize agent with model, tools, memory |
run() | (input: string | AgentInput): Promise<AgentOutput> | Execute agent and return final result |
reset() | (): void | Clear memory and reset state |
_transform() | ($i, $o): void | Component integration for pipelines |
Usage Example:
See Base Agent for detailed implementation information.
Sources:
The StreamingAgent class in packages/components/src/agents/StreamingAgent.ts88-468 wraps the base Agent to provide real-time execution updates through chunk emission.
Chunk Types:
The runStream() method yields StreamingChunk objects with different types:
| Chunk Type | Description | Fields |
|---|---|---|
iteration_start | New iteration begins | iteration |
model_thinking | Model is processing | - |
assistant_message | Model response received | content, toolCalls |
tool_start | Tool execution begins | toolName |
tool_result | Tool execution complete | toolName, result |
completed | Agent finished | finalMessage, history, allToolCalls |
error | Error occurred | error |
Usage Example:
This enables building responsive UIs that show progress in real-time. See Streaming Agent for details.
Sources:
Agents are configured via the AgentConfig object passed to the constructor. The configuration determines the agent's capabilities and behavior.
Configuration Flow:
Sources:
The buildSystemPrompt() method at packages/components/src/agents/index.ts357-390 generates a comprehensive system prompt by combining the base prompt with tool descriptions:
config.systemPrompt"\n\n可用工具:\n""${index + 1}. ${tool.name} - ${tool.description}\n"tool.parameters.properties, add " - ${name}: ${description}\n"This creates a system message that informs the model about available tools and their usage. The resulting system message is added to memory during initialization.
Sources:
Initialization Sequence:
Sources:
The reset() method at packages/components/src/agents/index.ts634-637 clears agent state:
currentIteration to 0initializeMemory() which clears memory and rebuilds system promptThis allows reusing an agent instance for new conversations.
Sources:
Agents can be executed independently without a pipeline by calling the run() method directly:
This is the most common usage pattern for agents. See examples/agent-with-tools/index.ts116-156 for a complete example.
Sources:
Agents extend the Component base class and can be integrated into pipelines like any other component. The agent's _transform() method at packages/components/src/agents/index.ts593-627 handles port-based communication:
Port Behavior:
'in' - Accepts string | AgentInput'out' - Emits AgentOutput after execution completesSources:
The StreamingAgent is commonly used in web applications to provide real-time feedback. Example from the serve-astack backend:
See Serve-AStack Chat Application for the complete full-stack implementation.
Sources:
The Agent's executeWithTools() method at packages/components/src/agents/index.ts438-514 implements robust error handling for tool execution:
Error Types and Responses:
| Error Scenario | Detection Point | Handling Behavior |
|---|---|---|
| Tool not found | tools.find() returns undefined | Add error message to toolResultsText, continue processing other tools |
| Argument parsing failed | JSON.parse() throws exception | Add parse error to toolResultsText, continue loop |
| No executable method | No execute or invoke property | Add method error to toolResultsText, continue loop |
| Tool execution throws | tool.execute() or tool.invoke() throws | Catch error, add to toolResultsText, record in toolCalls[] with error result |
Error Flow:
All errors are:
verbose: truetoolResultsTexttoolCalls array in AgentOutputSources:
The maxIterations configuration parameter prevents infinite loops. At packages/components/src/agents/index.ts411-534 the execution loop:
iteration counter at the start of each loopiteration < this.maxIterations before continuinghasMoreToolsToCall is true: "达到最大迭代次数 ${this.maxIterations},强制终止迭代"This prevents runaway execution when the model repeatedly requests tools without providing a final answer.
Sources:
When used in a pipeline, the agent's _transform() method at packages/components/src/agents/index.ts593-627 wraps execution in a try-catch block:
This ensures that pipeline execution continues even if the agent encounters an unrecoverable error.
Sources:
Agents work with any class that implements the ModelProvider interface. The most common pattern:
Sources:
Agents pass tools to models using the temporaryTools option:
The model provider converts these to its API format. For Deepseek:
Sources:
When verbose: true, the Agent logs detailed execution information:
[Agent Debug] === 迭代 1/10 === [Agent Debug] 发送消息给模型: [...] [Agent Debug] 收到模型回复: {...} [Agent Debug] 工具调用数量: 2 [Agent Debug] 工具 readFile 的参数: {...} [Agent Debug] 使用 execute 方法执行工具 readFile [Agent Debug] 工具 readFile 执行结果: "..." This provides insight into:
Sources:
The AgentOutput provides complete execution history:
This enables:
Sources:
Refresh this wiki