A3S Code 是一个可嵌入的 Rust 编码 Agent 框架。20 行代码,你就能构建一个具备 Claude Code 核心能力的终端助手。
import { Agent } from '@a3s-lab/code';
import * as readline from 'readline';
const agent = await Agent.create('agent.hcl');
const session = agent.session(process.cwd());
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
console.log('A3S Code — 输入你的问题,Ctrl+C 退出\n');
while (true) {
const input = await new Promise<string>((resolve) => rl.question('> ', resolve));
if (!input.trim()) continue;
const events = await session.stream(input);
for await (const event of events) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'tool_use') console.log(`\n[${event.tool}]`);
else if (event.type === 'end') console.log('\n');
}
}
这就是全部核心代码。 它已经具备:多轮对话、流式输出、工具执行(读文件、写文件、运行命令)、代码库上下文理解。
为什么这么简单? 因为 Claude Code 是终端工具,没有编程 API。OpenCode 也是 CLI,不能嵌入。A3S Code 是库——可以被你的代码直接调用,可以嵌入任何产品。
为什么编码智能体是 Agentic AI 的核心? 真正的"自主"需要一个条件:Agent 能够自己判断结果对不对,而不依赖人类来告诉它。客服 Agent 需要人类评价回答质量,写作 Agent 需要人类判断内容好坏——它们本质上是"执行者",不是"自主体"。编码 Agent 不同:编译器要么通过要么报错,测试要么绿要么红。这个客观的、可自动化的反馈回路让 Agent 能够真正自主——执行、验证、发现错误、自我修正,循环往复,不需要人类介入。一旦建立了这个能力,它可以迁移到任何有客观反馈的结构化环境:数据管道、基础设施配置、API 集成。这就是为什么编码智能体不只是 AI 的一个垂直应用,而是整个 Agentic AI 领域的核心形态。
| Claude Code | OpenCode | OpenClaw | A3S Code | |
|---|---|---|---|---|
| 核心定位 | 开发者终端工具 | 开放生态终端工具 | 消息平台个人助理 | 可嵌入 Agent 基础设施 |
| 使用方式 | CLI 交互 | CLI 交互 | 消息平台对话 | 代码调用(库) |
| 可嵌入性 | 无编程 API | 无编程 API | 无编程 API | 核心设计目标 |
| 扩展方式 | MCP + Skills + Hooks | MCP + 插件 | 插件 | Trait 扩展点 + MCP |
| 多租户 | 不支持 | 不支持 | 不支持 | 支持 |
| 并行任务 | 子 Agent 并行 | 有限支持 | 不支持 | Lane 队列 + 多机器分发 |
| 开源 | 否 | 是 | 是 | 是 |
这不是功能优劣的对比,是设计目标的对比。如果你在使用编码 Agent,Claude Code 是最成熟的选择。如果你在构建包含编码 Agent 能力的产品,A3S Code 提供了你需要的基础设施。
一、为什么 20 行就够了?极简核心 + 工具自举
这是构建 Agentic AI 系统最重要的架构原则,也是 A3S Code 的设计基础。
什么是极简核心?
极简核心的意思是:系统的不可替换部分应该尽可能小。
一个编码 Agent 的真正核心,只有五个组件:
Agent ← 配置加载、会话生命周期管理
AgentSession ← 工作区绑定的执行上下文
AgentLoop ← 驱动 LLM 轮次的执行引擎
ToolExecutor ← 工具注册、调度、执行
LlmClient ← LLM 提供商的统一抽象
这五个组件是系统的骨架。它们之间的关系是固定的:Agent 创建 AgentSession,AgentSession 持有 AgentLoop,AgentLoop 在每个轮次里调用 LlmClient 获取决策,再通过 ToolExecutor 执行工具。
这个骨架不应该随业务需求变化。它是稳定的、可测试的、可独立推理的。
什么是工具自举?
工具自举的意思是:Agent 的所有扩展能力,都通过工具来实现,而不是通过修改核心。
这个原则有两层含义:
第一层:内置工具覆盖基础能力。 文件读写、代码搜索、命令执行、网络请求——这些是编码 Agent 的基础动作,以内置工具的形式存在,开箱即用。
第二层:外部工具扩展专业能力。 数据库操作、代码审查、部署流水线、第三方 API——这些通过 MCP(Model Context Protocol)或自定义工具接入,不需要修改核心代码。
工具自举的关键洞察是:LLM 本身就是最好的工具路由器。 你不需要写复杂的意图识别逻辑,只需要给 LLM 提供足够清晰的工具描述,它会自己决定什么时候用什么工具。
这个设计的结果是:系统的能力边界由工具集决定,而工具集可以在运行时动态扩展,核心代码保持不变。
为什么这个原则重要?
考虑反面:如果你把权限控制、记忆管理、技能系统、MCP 集成都写进核心,会发生什么?
核心变得臃肿,每个新需求都需要修改核心,不同功能之间产生耦合,测试变得困难,维护成本指数级上升。
极简核心 + 工具自举把这些问题全部消解:核心只做一件事(驱动 LLM 轮次),其他一切都是可插拔的扩展。
在 A3S Code 里,这个原则体现为 19 个 trait 扩展点,每个都有默认实现:
// 不满意默认的权限系统?实现自己的
class MyPermissionChecker implements PermissionChecker {
async check(tool: string, args: unknown): Promise<Permission> {
// 你的逻辑
}
}
const session = agent.session('.', {
permissionChecker: new MyPermissionChecker(),
});
系统开箱即用,任何部分都可以替换,核心保持稳定。
工具自举的另一层含义:不需要预处理知识。 传统 RAG 的思路是"预先把知识向量化或图谱化,再检索注入"。但工具自举揭示了另一条路:Agent 不需要预先知道所有知识,它可以在需要的时候通过工具去读取。代码库不需要提前向量化——Agent 直接用 read_file、search_code 工具按需读取。这不只是省去了预处理的工程成本,更重要的是:工具调用本身就是最精准的上下文检索,因为是 Agent 自己决定读什么,而不是检索系统猜测什么相关。
二、A3S Code 的完整能力边界
极简核心 + 工具自举是架构原则,但 A3S Code 的实际能力边界远不止于此。下面系统介绍所有核心特性,包括记忆系统、上下文检索、Hooks、安全层、规划器等。
2.1 记忆系统:跨会话的长期记忆
MemoryStore 让 Agent 在多次会话之间保留关键信息。不同于 SessionStore(保存对话历史),MemoryStore 存储的是提炼后的知识——用户偏好、项目上下文、重要决策。
import { MemoryStore, Memory } from '@a3s-lab/code';
class VectorMemoryStore implements MemoryStore {
async save(memory: Memory): Promise<void> {
// 存储到向量数据库(如 Pinecone、Qdrant)
await vectorDB.upsert({
id: memory.id,
vector: await embed(memory.content),
metadata: { timestamp: memory.timestamp, tags: memory.tags },
});
}
async search(query: string, limit: number): Promise<Memory[]> {
// 语义搜索相关记忆
const results = await vectorDB.query(await embed(query), limit);
return results.map((r) => ({
id: r.id,
content: r.metadata.content,
timestamp: r.metadata.timestamp,
tags: r.metadata.tags,
}));
}
}
const session = agent.session('.', {
memoryStore: new VectorMemoryStore(),
});
// Agent 自动从记忆中检索相关上下文
await session.stream('继续上次的重构任务');
// → Agent 检索到「上次重构目标:auth 模块改用 JWT」
2.2 上下文检索(RAG):动态注入外部知识
ContextProvider 在每个轮次前自动检索相关文档,注入到 LLM 上下文。这是 RAG(Retrieval-Augmented Generation)的标准实现。
import { ContextProvider, ContextChunk } from '@a3s-lab/code';
class CodebaseContextProvider implements ContextProvider {
async retrieve(query: string, maxChunks: number): Promise<ContextChunk[]> {
// 从代码库索引中检索相关代码片段
const results = await codeSearch.search(query, maxChunks);
return results.map((r) => ({
content: r.code,
source: r.filePath,
score: r.relevance,
}));
}
}
const session = agent.session('.', {
contextProvider: new CodebaseContextProvider(),
});
// 用户问题触发自动检索
await session.stream('auth 模块的 JWT 验证逻辑在哪里?');
// → ContextProvider 检索到 src/auth/jwt.ts 的相关代码
// → LLM 基于检索到的代码回答
2.3 Hooks 系统:事件驱动的自动化
Hooks 在工具调用前后自动执行,用于日志记录、审计、自动化流程。
import { HookHandler, ToolCallEvent, ToolResultEvent } from '@a3s-lab/code';
class AuditHookHandler implements HookHandler {
async onToolCall(event: ToolCallEvent): Promise<void> {
// 工具调用前:记录审计日志
await auditLog.write({
timestamp: Date.now(),
tool: event.tool,
args: event.args,
sessionId: event.sessionId,
});
// 高风险操作:发送通知
if (['bash', 'write', 'delete'].includes(event.tool)) {
await slack.notify(`⚠️ Agent 正在执行 ${event.tool}`);
}
}
async onToolResult(event: ToolResultEvent): Promise<void> {
// 工具执行后:记录结果
await auditLog.write({
timestamp: Date.now(),
tool: event.tool,
success: !event.result.isError,
duration: event.duration,
});
}
}
const session = agent.session('.', {
hookHandler: new AuditHookHandler(),
});
2.4 安全层:输入污点分析和输出净化
SecurityProvider 在工具执行前检测输入是否包含恶意内容,在输出前净化敏感信息。
import { SecurityProvider, TaintAnalysis, SanitizeResult } from '@a3s-lab/code';
class ProductionSecurityProvider implements SecurityProvider {
async analyzeTaint(input: string): Promise<TaintAnalysis> {
// 检测命令注入、路径遍历、SQL 注入
const threats = [];
if (/;\s*(rm|curl|wget|nc)\s/.test(input)) threats.push('command_injection');
if (/\.\.[\\/\\]/.test(input)) threats.push('path_traversal');
if (/(union|select|drop|insert)\s+/i.test(input)) threats.push('sql_injection');
return {
isTainted: threats.length > 0,
threats,
riskLevel: threats.length > 0 ? 'high' : 'low',
};
}
async sanitizeOutput(output: string): Promise<SanitizeResult> {
// 移除敏感信息:API key、密码、token
let sanitized = output;
sanitized = sanitized.replace(/sk-[a-zA-Z0-9]{48}/g, '[REDACTED_API_KEY]');
sanitized = sanitized.replace(/password["\s:=]+[^\s"]+/gi, 'password=[REDACTED]');
sanitized = sanitized.replace(/Bearer\s+[^\s]+/g, 'Bearer [REDACTED]');
return { sanitized, redacted: sanitized !== output };
}
}
const session = agent.session('.', {
securityProvider: new ProductionSecurityProvider(),
});
2.5 规划器:复杂任务的自动分解
Planner 把复杂任务分解为子任务序列,Agent 按计划逐步执行。
import { Planner, Task, Plan } from '@a3s-lab/code';
class HierarchicalPlanner implements Planner {
async plan(goal: string, context: string): Promise<Plan> {
// 调用 LLM 生成任务分解
const response = await llm.complete({
prompt: `目标:${goal}\n上下文:${context}\n\n请分解为可执行的子任务序列。`,
});
const tasks: Task[] = parseTasksFromResponse(response);
return {
goal,
tasks,
estimatedSteps: tasks.length,
};
}
}
const session = agent.session('.', {
planner: new HierarchicalPlanner(),
});
// 复杂任务自动分解
await session.stream('重构整个 auth 模块,改用 JWT,添加 refresh token 机制,更新所有测试');
// → Planner 分解为:
// 1. 阅读现有 auth 代码
// 2. 设计 JWT + refresh token 方案
// 3. 实现新的 auth 逻辑
// 4. 更新测试
// 5. 验证所有测试通过
2.6 上下文压缩:自动管理 Token 预算
当对话历史超过阈值时,ContextCompactor 自动压缩旧轮次,保留关键信息。
// 在 agent.hcl 中配置
context_compaction {
enabled = true
trigger_threshold = 100000 # 超过 10 万 token 触发压缩
target_size = 50000 # 压缩到 5 万 token
strategy = "semantic" # 语义压缩(保留关键信息)
}
压缩策略:
- Truncate:直接删除最早的轮次
- Summarize:用 LLM 总结旧轮次,保留摘要
- Semantic:基于语义相似度保留最相关的轮次
2.7 多语言 SDK:Rust / Node.js / Python
A3S Code 是 Rust 核心库,通过 FFI 提供 Node.js 和 Python 原生绑定。
Rust API(零开销,最高性能):
use a3s_code::{Agent, AgentSession};
#[tokio::main]
async fn main() -> Result<()> {
let agent = Agent::new("agent.hcl").await?;
let session = agent.session("/project", None)?;
let mut stream = session.stream("重构 auth 模块").await?;
while let Some(event) = stream.next().await {
match event {
Event::TextDelta(text) => print!("{}", text),
Event::ToolUse(tool) => println!("\n[{}]", tool.name),
Event::End => println!(),
_ => {}
}
}
Ok(())
}
Python SDK(异步优先,类型提示):
from a3s_code import Agent, SessionLane
import asyncio
async def main():
agent = await Agent.create("agent.hcl")
session = agent.session(".", tools=finance_tools)
# 并行研究
tasks = [
{"prompt": f"分析 {sym}", "lane": SessionLane.GENERATE}
for sym in ["AAPL", "MSFT", "NVDA"]
]
results = await session.submit_batch(tasks)
print(results)
asyncio.run(main())
2.8 特性总结
| 特性 | 用途 | 扩展点 |
|---|---|---|
| 记忆系统 | 跨会话长期记忆 | MemoryStore |
| 上下文检索 | RAG 动态注入知识 | ContextProvider |
| Hooks | 事件驱动自动化 | HookHandler |
| 安全层 | 输入污点分析、输出净化 | SecurityProvider |
| 规划器 | 复杂任务分解 | Planner |
| 上下文压缩 | 自动管理 token 预算 | 配置驱动 |
| 多语言 SDK | Rust/Node.js/Python | 原生绑定 |
这些特性全部是可选扩展——系统有默认实现,开箱即用;如果需要定制,实现对应的 trait 即可。核心代码保持不变。
2.9 上下文工程:渐进式披露
上下文工程(Context Engineering)的核心问题是:如何在有限的 token 预算内,让 Agent 在每个轮次都拥有恰好足够的信息?
答案是渐进式披露(Progressive Disclosure):Agent 不是一次性把所有知识塞进上下文,而是按需、分层地获取信息。
以理解一个陌生代码库为例,Agent 的自然行为是:
- 读目录结构 → 了解全局布局(低成本,高覆盖)
- 读关键文件的顶部注释 → 了解模块职责(中等成本)
- 定位具体函数 → 读取实现细节(高成本,精准)
每一步都是按需披露,上下文始终保持精简。这比"把整个代码库向量化后检索"更准确,因为 Agent 自己知道它需要什么。
A3S Code 的实现:
// ContextProvider:每个轮次前自动检索相关上下文
class ProgressiveContextProvider implements ContextProvider {
async retrieve(query: string, maxChunks: number): Promise<ContextChunk[]> {
// 第一层:目录结构(总是注入)
const structure = await getProjectStructure();
// 第二层:语义相关的文件摘要
const summaries = await searchFileSummaries(query, maxChunks - 1);
// 第三层:精确匹配的代码片段(按需)
const snippets = await searchCodeSnippets(query, 2);
return [structure, ...summaries, ...snippets];
}
}
const session = agent.session('.', {
contextProvider: new ProgressiveContextProvider(),
// MemoryStore 保留跨会话的关键发现,避免重复探索
memoryStore: new FileMemoryStore('.a3s/memory'),
});
ContextProvider 控制每轮注入什么,MemoryStore 保留跨会话的关键知识,ContextCompactor 在 token 超限时自动压缩旧轮次——三者共同构成 A3S Code 的上下文工程体系。
三、A3S Code + A3S Box:给 Agent 提供沙箱环境
Agent 执行代码时,默认在宿主机上运行——这意味着恶意代码、意外删除、资源耗尽等风险直接暴露给你的系统。A3S Box 是一个轻量级 MicroVM 沙箱,为 Agent 的代码执行提供完全隔离的环境。
3.1 A3S Box 是什么?
A3S Box 是基于 libkrun 的嵌入式 MicroVM 沙箱,特点是:
- 轻量级:启动时间 < 100ms,内存占用 < 50MB
- 无守护进程:直接嵌入你的应用,不需要 Docker daemon
- 完全隔离:独立的文件系统、网络、进程空间
- TEE 支持:可选的可信执行环境(AMD SEV-SNP)
状态机:Created → Ready → Busy → Stopped
3.2 为什么 Agent 需要沙箱?
考虑这个场景:用户让 Agent「清理项目中的临时文件」,Agent 执行了 rm -rf /tmp/*——但由于路径解析错误,实际执行的是 rm -rf /*。
没有沙箱:宿主机文件系统被破坏。
有沙箱:只有 Box 内的文件系统受影响,宿主机安全。
其他风险场景:
- Agent 下载并执行恶意脚本
- Agent 启动占用所有 CPU 的进程
- Agent 意外暴露敏感文件(如
.env)
A3S Box 把这些风险全部隔离在沙箱内。
3.3 集成方式:将 Agent 的代码执行路由到 Box
import { Agent } from '@a3s-lab/code';
import { BoxSdk } from '@a3s-lab/box';
async function main() {
// 创建 Box SDK 实例
const boxSdk = new BoxSdk();
// 创建沙箱:Alpine Linux,512MB 内存,挂载当前目录
const sandbox = boxSdk.create({
image: 'alpine:latest',
memoryMb: 512,
mounts: [{ hostPath: process.cwd(), guestPath: '/workspace', readonly: false }],
workdir: '/workspace',
});
// 定义 Box 工具:在沙箱内执行命令
const boxTools = [
{
name: 'bash',
description: '在隔离的沙箱环境中执行 shell 命令',
parameters: {
type: 'object',
properties: {
command: { type: 'string', description: 'Shell 命令' },
},
required: ['command'],
},
execute: async (args: { command: string }) => {
const result = await sandbox.exec('sh', ['-c', args.command]);
return {
content: result.stdout,
isError: result.exitCode !== 0,
};
},
},
];
// Agent 的 bash 工具现在路由到 Box
const agent = await Agent.create('agent.hcl');
const session = agent.session('.', { tools: boxTools });
// 用户请求执行危险操作,但只影响沙箱
await session.stream('删除所有 .tmp 文件');
// → Agent 调用 bash 工具
// → 命令在 Box 内执行,宿主机安全
// 任务完成后停止沙箱
sandbox.stop();
}
3.4 扩展 Box 工具:文件上传/下载、快照
除了命令执行,Box 还支持文件传输和快照管理:
const boxTools = [
{
name: 'box_exec',
description: '在沙箱中执行命令',
execute: async (args: { command: string }) => {
const result = await sandbox.exec('sh', ['-c', args.command]);
return { content: result.stdout, isError: result.exitCode !== 0 };
},
},
{
name: 'box_upload',
description: '上传文件到沙箱',
parameters: {
type: 'object',
properties: {
localPath: { type: 'string' },
guestPath: { type: 'string' },
},
required: ['localPath', 'guestPath'],
},
execute: async (args: { localPath: string; guestPath: string }) => {
const data = await fs.readFile(args.localPath);
await sandbox.upload(data, args.guestPath);
return { content: `已上传 ${args.localPath} → ${args.guestPath}` };
},
},
{
name: 'box_download',
description: '从沙箱下载文件',
parameters: {
type: 'object',
properties: {
guestPath: { type: 'string' },
localPath: { type: 'string' },
},
required: ['guestPath', 'localPath'],
},
execute: async (args: { guestPath: string; localPath: string }) => {
const data = await sandbox.download(args.guestPath);
await fs.writeFile(args.localPath, data);
return { content: `已下载 ${args.guestPath} → ${args.localPath}` };
},
},
];
3.5 Skill 机制:教 Agent 如何操作 Box
通过 Skill 文件,你可以教 Agent 在什么场景下使用 Box,以及如何安全地操作沙箱。
<!-- skills/box_operator.md -->
# Box 沙箱操作员
## 可用工具
- `box_exec`: 在沙箱中执行命令
- `box_upload`: 上传文件到沙箱
- `box_download`: 从沙箱下载文件
## 操作规范
### 何时使用沙箱
以下操作**必须**在沙箱中执行,不得在宿主机上运行:
- 执行用户提供的脚本或命令
- 安装第三方依赖(npm install, pip install)
- 运行测试(可能包含恶意测试用例)
- 编译未知来源的代码
- 任何涉及 `rm`、`mv`、`chmod` 的文件操作
### 安全检查清单
在执行任何命令前,检查:
1. 命令是否包含 `rm -rf /`、`:(){ :|:& };:` 等危险模式
2. 是否需要 root 权限(沙箱内无 root)
3. 是否需要网络访问(默认隔离)
### 文件传输规范
- 上传前验证文件大小(< 100MB)
- 下载前验证路径(不得包含 `..`)
- 敏感文件(.env, id_rsa)不得上传到沙箱
## 示例工作流
用户请求:「运行项目的测试套件」
1. 检查测试命令(如 `npm test`)
2. 上传项目文件到沙箱 `/workspace`
3. 在沙箱中执行 `npm install && npm test`
4. 下载测试报告到宿主机
5. 停止沙箱释放资源
加载 Skill 后,Agent 会自动遵循这些规范:
const session = agent.session('.', {
tools: boxTools,
skills: ['box_operator'],
});
// Agent 自动判断需要使用沙箱
await session.stream('帮我运行测试,然后清理所有临时文件');
// → Agent 读取 box_operator skill
// → 识别「运行测试」和「清理文件」是危险操作
// → 自动使用 box_exec 在沙箱中执行
// → 宿主机安全
3.6 完整示例:沙箱化的编码 Agent
import { Agent } from '@a3s-lab/code';
import { BoxSdk } from '@a3s-lab/box';
import * as fs from 'fs/promises';
async function main() {
const boxSdk = new BoxSdk();
const sandbox = boxSdk.create({
image: 'node:20-alpine',
memoryMb: 1024,
mounts: [{ hostPath: process.cwd(), guestPath: '/workspace' }],
workdir: '/workspace',
network: true, // 允许网络访问(npm install)
});
const boxTools = [
{
name: 'bash',
description: '在隔离沙箱中执行命令',
execute: async (args: { command: string }) => {
const result = await sandbox.exec('sh', ['-c', args.command]);
return { content: result.stdout, isError: result.exitCode !== 0 };
},
},
];
const agent = await Agent.create('agent.hcl');
const session = agent.session('.', {
tools: boxTools,
skills: ['box_operator'],
});
console.log('沙箱化编码 Agent 就绪。所有代码执行都在隔离环境中进行。\n');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.on('close', () => {
sandbox.stop();
process.exit(0);
});
while (true) {
const input = await new Promise<string>((resolve) => rl.question('> ', resolve));
if (!input.trim()) continue;
const events = await session.stream(input);
for await (const event of events) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'tool_use') process.stdout.write(`\n[沙箱] ${event.tool} `);
else if (event.type === 'end') console.log('\n');
}
}
}
main().catch(console.error);
3.7 Box 的其他能力
持久化工作区:多次会话共享同一个沙箱状态
const sandbox = boxSdk.create({
image: 'ubuntu:22.04',
workspace: { name: 'my-project', guestPath: '/workspace' },
});
// 工作区内容在沙箱停止后保留,下次启动时恢复
端口转发:访问沙箱内的服务
const sandbox = boxSdk.create({
image: 'node:20',
portForwards: [{ guestPort: 3000, hostPort: 3000 }],
});
// 沙箱内的 3000 端口映射到宿主机 3000
TEE 模式:可信执行环境(需要硬件支持)
const sandbox = boxSdk.create({
image: 'alpine:latest',
tee: true, // 启用 AMD SEV-SNP
});
// 沙箱内存加密,宿主机无法读取
四、用 TypeScript SDK 构建类 Claude Code 的产品
理解了架构原则,现在来实践。我们用 A3S Code 的 TypeScript SDK 构建一个具备 Claude Code 核心能力的终端编码助手。
目标产品具备:
- 多轮对话,理解代码库上下文
- 流式输出,实时显示 Agent 思考过程
- 工具执行(读文件、写文件、运行命令)
- 权限控制,敏感操作需要用户确认
- MCP 服务器支持,动态扩展工具集
- 会话持久化,支持恢复上次对话
4.1 安装和配置
npm install @a3s-lab/code
创建 agent.hcl 配置文件:
# 支持任何 OpenAI 兼容端点
default_model = "anthropic/claude-sonnet-4-20250514"
providers {
name = "anthropic"
api_key = env("ANTHROPIC_API_KEY")
}
# 可选:接入 MCP 服务器
mcp_servers {
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "."]
}
4.2 核心会话循环
这是整个产品的骨架——一个读取用户输入、流式输出 Agent 响应的循环。升级版本展示完整的事件处理:thinking 过程、工具调用结果、token 用量统计、以及中断恢复:
import { Agent, AgentSession, StreamEvent } from '@a3s-lab/code';
import * as readline from 'readline';
const agent = await Agent.create('agent.hcl');
const session = agent.session(process.cwd());
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
// 优雅退出:Ctrl+C 时等待当前轮次完成
let currentAbort: AbortController | null = null;
rl.on('close', async () => {
currentAbort?.abort();
await session.flush(); // 等待持久化完成
process.exit(0);
});
console.log('A3S Code — 输入你的问题,Ctrl+C 退出\n');
while (true) {
const input = await new Promise<string>((resolve) => rl.question('> ', resolve));
if (!input.trim()) continue;
currentAbort = new AbortController();
const startTime = Date.now();
try {
const events = await session.stream(input, { signal: currentAbort.signal });
let toolCount = 0;
let inputTokens = 0;
let outputTokens = 0;
for await (const event of events) {
switch (event.type) {
case 'thinking':
// Agent 的推理过程(仅在支持 extended thinking 的模型上出现)
process.stdout.write(`\x1b[2m${event.thinking}\x1b[0m`);
break;
case 'text_delta':
process.stdout.write(event.text);
break;
case 'tool_use':
toolCount++;
process.stdout.write(`\n\x1b[36m[${event.tool}]\x1b[0m `);
break;
case 'tool_result':
// 工具执行完成:显示耗时和结果摘要
const preview = typeof event.result.content === 'string'
? event.result.content.slice(0, 80).replace(/\n/g, ' ')
: '[binary]';
process.stdout.write(
event.result.isError
? `\x1b[31m✗ ${preview}\x1b[0m\n`
: `\x1b[32m✓\x1b[0m ${preview}…\n`
);
break;
case 'usage':
// token 用量(每轮结束时触发)
inputTokens = event.inputTokens;
outputTokens = event.outputTokens;
break;
case 'end':
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
console.log(
`\n\x1b[2m[${toolCount} tools · ${inputTokens}↑ ${outputTokens}↓ tokens · ${elapsed}s]\x1b[0m\n`
);
break;
}
}
} catch (err) {
if ((err as Error).name === 'AbortError') {
console.log('\n[已中断]\n');
} else {
console.error(`\n\x1b[31m错误:${(err as Error).message}\x1b[0m\n`);
}
} finally {
currentAbort = null;
}
}
4.3 添加权限控制
Claude Code 的一个核心设计是:危险操作需要用户确认。我们用 A3S Code 的权限系统实现同样的效果:
import { Agent, PermissionChecker, Permission } from '@a3s-lab/code';
import * as readline from 'readline';
// 需要确认的高风险工具
const DANGEROUS_TOOLS = new Set(['bash', 'write', 'edit', 'patch']);
class InteractivePermissionChecker implements PermissionChecker {
private rl: readline.Interface;
constructor(rl: readline.Interface) {
this.rl = rl;
}
async check(tool: string, args: unknown): Promise<Permission> {
// 只读工具直接放行
if (!DANGEROUS_TOOLS.has(tool)) {
return Permission.Allow;
}
// 显示将要执行的操作
const preview = this.formatPreview(tool, args);
console.log(`\n⚠️ Agent 想要执行:\n${preview}`);
const answer = await new Promise<string>((resolve) => {
this.rl.question('允许?[y/N] ', resolve);
});
return answer.toLowerCase() === 'y' ? Permission.Allow : Permission.Deny;
}
private formatPreview(tool: string, args: unknown): string {
const a = args as Record<string, unknown>;
switch (tool) {
case 'bash':
return ` $ ${a.command}`;
case 'write':
return ` 写入文件: ${a.file_path}`;
case 'edit':
return ` 编辑文件: ${a.file_path}`;
default:
return ` ${tool}: ${JSON.stringify(args, null, 2)}`;
}
}
}
// 集成到 session
const session = agent.session(process.cwd(), {
permissionChecker: new InteractivePermissionChecker(rl),
});
4.4 添加 MCP 服务器动态注册
Claude Code 支持在配置文件里声明 MCP 服务器。A3S Code 还支持在运行时动态注册,这让你可以根据用户的项目类型按需加载工具:
// 检测项目类型,按需加载 MCP 服务器
async function loadProjectMcpServers(session: AgentSession, projectPath: string) {
const fs = await import('fs/promises');
// 检测到 package.json → 加载 Node.js 相关工具
try {
await fs.access(`${projectPath}/package.json`);
const count = await session.addMcpServer(
'nodejs-tools',
'npx',
['-y', '@modelcontextprotocol/server-filesystem', projectPath],
);
console.log(`[MCP] 加载 Node.js 工具集,${count} 个工具可用`);
} catch {}
// 检测到 Cargo.toml → 加载 Rust 相关工具
try {
await fs.access(`${projectPath}/Cargo.toml`);
const count = await session.addMcpServer(
'rust-tools',
'npx',
['-y', '@modelcontextprotocol/server-filesystem', projectPath],
);
console.log(`[MCP] 加载 Rust 工具集,${count} 个工具可用`);
} catch {}
}
4.5 添加会话持久化
Claude Code 支持恢复上次会话。A3S Code 通过 SessionStore trait 实现同样的能力:
import { SessionStore, SessionData } from '@a3s-lab/code';
import * as fs from 'fs/promises';
import * as path from 'path';
class FileSessionStore implements SessionStore {
private storePath: string;
constructor(storePath: string) {
this.storePath = storePath;
}
async save(sessionId: string, data: SessionData): Promise<void> {
const filePath = path.join(this.storePath, `${sessionId}.json`);
await fs.mkdir(this.storePath, { recursive: true });
await fs.writeFile(filePath, JSON.stringify(data, null, 2));
}
async load(sessionId: string): Promise<SessionData | null> {
const filePath = path.join(this.storePath, `${sessionId}.json`);
try {
const content = await fs.readFile(filePath, 'utf-8');
return JSON.parse(content);
} catch {
return null;
}
}
async delete(sessionId: string): Promise<void> {
const filePath = path.join(this.storePath, `${sessionId}.json`);
await fs.unlink(filePath).catch(() => {});
}
}
// 使用项目目录作为会话 ID,实现「每个项目一个会话」
const projectId = Buffer.from(process.cwd()).toString('base64url');
const session = agent.session(process.cwd(), {
sessionId: projectId,
sessionStore: new FileSessionStore(path.join(process.env.HOME!, '.a3s/sessions')),
permissionChecker: new InteractivePermissionChecker(rl),
});
4.6 添加斜杠命令
Claude Code 有 /help、/clear、/cost 等内置命令。A3S Code 的 SlashCommand 接口让你实现同样的功能:
import { SlashCommand, CommandContext, CommandOutput } from '@a3s-lab/code';
// /cost 命令:显示本次会话的 token 消耗
class CostCommand implements SlashCommand {
name = 'cost';
description = '显示本次会话的 token 消耗和估算费用';
execute(_args: string, ctx: CommandContext): CommandOutput {
const usage = ctx.tokenUsage;
// Claude Sonnet 4 定价(仅供参考)
const inputCost = (usage.promptTokens / 1_000_000) * 3.0;
const outputCost = (usage.completionTokens / 1_000_000) * 15.0;
const total = inputCost + outputCost;
return CommandOutput.text(
`Token 消耗:\n` +
` 输入:${usage.promptTokens.toLocaleString()} tokens ($${inputCost.toFixed(4)})\n` +
` 输出:${usage.completionTokens.toLocaleString()} tokens ($${outputCost.toFixed(4)})\n` +
` 合计:$${total.toFixed(4)}`
);
}
}
// /clear 命令:清空对话历史
class ClearCommand implements SlashCommand {
name = 'clear';
description = '清空对话历史,开始新会话';
execute(_args: string, ctx: CommandContext): CommandOutput {
ctx.clearHistory();
return CommandOutput.text('对话历史已清空');
}
}
session.registerCommand(new CostCommand());
session.registerCommand(new ClearCommand());
4.7 完整产品组装
把所有部分组合起来:
import { Agent } from '@a3s-lab/code';
import * as readline from 'readline';
import * as path from 'path';
async function main() {
const agent = await Agent.create('agent.hcl');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
});
// 处理 Ctrl+C
rl.on('close', () => {
console.log('\n再见!');
process.exit(0);
});
const projectId = Buffer.from(process.cwd()).toString('base64url');
const session = agent.session(process.cwd(), {
sessionId: projectId,
sessionStore: new FileSessionStore(
path.join(process.env.HOME!, '.a3s/sessions')
),
permissionChecker: new InteractivePermissionChecker(rl),
});
// 注册命令
session.registerCommand(new CostCommand());
session.registerCommand(new ClearCommand());
// 按需加载 MCP 服务器
await loadProjectMcpServers(session, process.cwd());
// 显示欢迎信息
const isResumed = await session.hasHistory();
if (isResumed) {
console.log('✓ 已恢复上次会话。输入 /clear 开始新对话。\n');
} else {
console.log('A3S Code — 输入你的问题,/help 查看命令,Ctrl+C 退出\n');
}
// 主循环
while (true) {
const input = await new Promise<string>((resolve) => {
rl.question('> ', resolve);
});
if (!input.trim()) continue;
// 斜杠命令
if (input.startsWith('/')) {
const output = await session.executeCommand(input);
console.log(output.text);
continue;
}
// Agent 流式响应
try {
const events = await session.stream(input);
for await (const event of events) {
if (event.type === 'text_delta') {
process.stdout.write(event.text);
} else if (event.type === 'tool_use') {
process.stdout.write(`\n[${event.tool}] `);
} else if (event.type === 'end') {
console.log('\n');
}
}
} catch (err) {
console.error(`\n错误:${err instanceof Error ? err.message : err}\n`);
}
}
}
main().catch(console.error);
这个产品已经具备了 Claude Code 的核心能力:多轮对话、流式输出、工具执行、权限控制、MCP 支持、会话持久化、斜杠命令。代码量不到 200 行。
五、用编码智能体构建 Agentic 金融应用
编码智能体不只是为开发者服务的工具——它是构建任何领域 Agentic 应用的基础设施。真正的 Agentic 应用和普通聊天机器人的区别在于:它能自主规划、并行执行、协调多个专业 Agent 协作,而不只是被动响应单条指令。
下面用 A3S Code TypeScript SDK 构建一个金融研究系统,展示四个核心 Agentic 特性:技能系统、自动规划、Agent Team 和并行研究分析。
5.1 技能系统:定义专业行为规范
技能(Skill)是 Markdown 格式的行为规范文件,告诉 Agent 在特定场景下应该遵循什么流程。它不是代码,而是结构化的专业知识。
<!-- skills/portfolio_analyst.md -->
# 投资组合分析师
## 分析流程
收到投资组合分析请求时,**必须**按以下顺序执行,不得跳过任何步骤:
1. **数据收集**:调用 get_portfolio 获取所有持仓,调用 get_quote 获取实时报价
2. **并行研究**:对每只持仓股票同时启动独立分析任务(使用 submit_batch)
3. **风险评估**:计算组合整体波动率、集中度风险、相关性
4. **生成报告**:输出结构化报告,包含持仓概览、风险评级、调仓建议
## 报告格式
\`\`\`
## 投资组合分析报告
**分析时间**: {timestamp}
**总市值**: ${total_value} **总盈亏**: ${total_pnl} ({pnl_pct}%)
### 持仓明细
| 股票 | 持仓 | 成本 | 现价 | 盈亏 | 风险 |
...
### 风险评估
- 组合集中度: {concentration}
- 最高风险持仓: {symbol}
- 建议: {recommendation}
\`\`\`
## 注意事项
- 所有建议必须基于数据,不得主观臆断
- 高风险持仓必须在报告中明确标注
- 调仓建议需说明理由
在 HCL 配置中加载技能:
# agent.hcl
default_model = "anthropic/claude-sonnet-4-20250514"
providers {
name = "anthropic"
api_key = env("ANTHROPIC_API_KEY")
}
# 加载技能文件目录
skills_dir = "./skills"
技能系统的价值在于可复用的专业知识:同一套分析流程可以被不同的 Agent 实例加载,确保行为一致性,也方便团队协作维护。
5.2 自动规划:一句话触发完整分析流程
当用户说「帮我做一份完整的投资组合分析」时,Agent 不会直接回答——它会先规划,再执行。
import { Agent, SessionLane } from '@a3s-lab/code';
const agent = await Agent.create('agent.hcl');
// 加载投资组合分析师技能
const session = agent.session('.', {
tools: financeTools,
skills: ['portfolio_analyst'], // 注入专业行为规范
});
// 用户只需一句话,Agent 自动规划并执行完整流程:
// 1. 调用 get_portfolio 获取持仓
// 2. 调用 get_quote 批量获取报价
// 3. 启动并行研究任务(每只股票独立分析)
// 4. 汇总结果,生成结构化报告
const events = await session.stream(
'帮我做一份完整的投资组合分析,重点关注风险敞口和调仓建议'
);
for await (const event of events) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'tool_use') console.log(`\n→ [${event.tool}]`);
else if (event.type === 'end') console.log('\n');
}
这里的关键是:技能文件定义了规划逻辑,Agent 自主决定调用顺序和工具组合。你不需要写任何编排代码。
5.3 并行研究:同时分析多只股票
对多只股票做深度研究时,串行执行会很慢。submitBatch 让多个分析任务并行运行,并支持进度追踪和部分失败处理:
import { Agent, SessionLane, BatchResult } from '@a3s-lab/code';
async function parallelStockResearch(symbols: string[]) {
const agent = await Agent.create('agent.hcl');
const session = agent.session('.', { tools: financeTools });
// 为每只股票创建独立的深度研究任务
const researchTasks = symbols.map((sym) => ({
id: sym, // 任务 ID,用于追踪进度
prompt: `对 ${sym} 进行深度分析:
1. 获取实时报价和成交量
2. 评估当前风险等级(低/中/高)
3. 基于数据给出买入/持有/卖出建议
输出结构化 JSON:{ symbol, price, volume, risk, recommendation, rationale }`,
lane: SessionLane.Generate,
}));
console.log(`启动 ${symbols.length} 个并行研究任务...\n`);
// 进度回调:每个任务完成时实时输出
const results = await session.submitBatch(researchTasks, {
onProgress: (completed, total, result: BatchResult) => {
const icon = result.error ? '✗' : '✓';
const summary = result.error
? result.error.message
: JSON.parse(result.output).recommendation ?? 'done';
console.log(`[${completed}/${total}] ${icon} ${result.id}: ${summary}`);
},
// 部分失败不中断:收集所有结果后统一处理
continueOnError: true,
});
// 分离成功和失败的任务
const succeeded = results.filter((r) => !r.error);
const failed = results.filter((r) => r.error);
if (failed.length > 0) {
console.warn(`\n⚠ ${failed.length} 个任务失败:${failed.map((r) => r.id).join(', ')}`);
}
// 把成功的结果交给汇总 Agent
const summarySession = agent.session('.', { tools: financeTools });
const summaryEvents = await summarySession.stream(
`以下是对各股票的独立研究结果(${succeeded.length}/${symbols.length} 成功):\n` +
`${JSON.stringify(succeeded.map((r) => JSON.parse(r.output)), null, 2)}\n\n` +
`请综合以上分析,生成投资组合优化建议,包含风险分散建议和仓位调整方案。` +
(failed.length > 0 ? `\n注意:${failed.map((r) => r.id).join(', ')} 数据缺失,建议保守处理。` : '')
);
for await (const event of summaryEvents) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'end') console.log('\n');
}
}
// 并行研究 4 只股票,耗时约等于单只股票的分析时间
await parallelStockResearch(['AAPL', 'MSFT', 'NVDA', 'TSLA']);
5.4 Agent Team:专业分工协作
复杂的金融分析需要不同专业能力的协作。Agent Team 让你把任务分配给专门的 Worker Agent,由 Lead Agent 统一协调。
import { Agent, AgentTeam } from '@a3s-lab/code';
async function buildFinanceTeam() {
// Lead Agent:接收用户请求,规划任务,分配给 Worker,汇总结果
const lead = await Agent.create('agent.hcl');
const leadSession = lead.session('.', {
tools: financeTools,
skills: ['portfolio_analyst'],
role: 'lead',
});
// Worker 1:市场分析师,专注行情数据和技术指标
const marketAnalyst = await Agent.create('agent.hcl');
const marketSession = marketAnalyst.session('.', {
tools: [financeTools.find((t) => t.name === 'get_quote')!],
systemPrompt: '你是市场分析师,专注于股票行情数据、成交量分析和价格趋势。',
role: 'worker',
workerId: 'market_analyst',
});
// Worker 2:风险分析师,专注风险评估和压力测试
const riskAnalyst = await Agent.create('agent.hcl');
const riskSession = riskAnalyst.session('.', {
tools: [financeTools.find((t) => t.name === 'risk_assessment')!],
systemPrompt: '你是风险分析师,专注于波动率计算、风险敞口评估和压力测试。',
role: 'worker',
workerId: 'risk_analyst',
});
// 组建 Team,Lead 可以把子任务委派给 Worker
const team = AgentTeam.create({
lead: leadSession,
workers: [marketSession, riskSession],
});
// Lead 接收用户请求,自动决定哪些子任务交给哪个 Worker
// 例如:行情数据 → market_analyst,风险计算 → risk_analyst
// 两个 Worker 并行工作,Lead 汇总结果后回复用户
const events = await team.stream(
'分析我的持仓,市场分析师负责行情,风险分析师负责风险评估,最后给我综合建议'
);
for await (const event of events) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'worker_started') {
console.log(`\n[Team] ${event.workerId} 开始工作...`);
} else if (event.type === 'worker_completed') {
console.log(`\n[Team] ${event.workerId} 完成`);
} else if (event.type === 'end') {
console.log('\n');
}
}
}
buildFinanceTeam().catch(console.error);
5.5 完整系统:四个特性协同工作
把以上特性组合成一个完整的金融研究终端:
import { Agent, AgentTeam, SessionLane } from '@a3s-lab/code';
import * as readline from 'readline';
async function main() {
const agent = await Agent.create('agent.hcl');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.on('close', () => process.exit(0));
// 主会话:加载技能,具备自动规划能力
const session = agent.session('.', {
tools: financeTools,
skills: ['portfolio_analyst'],
role: 'lead',
queueConfig: { queryMaxConcurrency: 4 }, // Query 通道最多 4 个并行
});
// 注册斜杠命令
session.registerCommand({
name: 'research',
description: '并行研究多只股票,用法: /research AAPL MSFT NVDA',
execute: async (args) => {
const symbols = args.trim().split(/\s+/).filter(Boolean);
if (symbols.length === 0) return { text: '用法: /research AAPL MSFT NVDA' };
console.log(`\n启动 ${symbols.length} 个并行研究任务...\n`);
const tasks = symbols.map((sym) => ({
prompt: `分析 ${sym}:报价、风险等级、投资建议`,
lane: SessionLane.Generate,
}));
const results = await session.submitBatch(tasks);
return { text: JSON.stringify(results, null, 2) };
},
});
console.log('金融研究系统就绪。\n');
console.log(' > 帮我做一份完整的投资组合分析 (自动规划 + 技能系统)');
console.log(' > /research AAPL MSFT NVDA TSLA (并行研究)');
console.log(' > 组建分析团队,深度研究科技股板块 (Agent Team)\n');
while (true) {
const input = await new Promise<string>((resolve) => rl.question('> ', resolve));
if (!input.trim()) continue;
if (input.startsWith('/')) {
const output = await session.executeCommand(input);
console.log(output.text + '\n');
continue;
}
const events = await session.stream(input);
for await (const event of events) {
if (event.type === 'text_delta') process.stdout.write(event.text);
else if (event.type === 'tool_use') process.stdout.write(`\n→ [${event.tool}] `);
else if (event.type === 'end') console.log('\n');
}
}
}
main().catch(console.error);
这个系统和普通聊天机器人的本质区别:用户说一句「做完整分析」,系统会自主规划步骤、并行执行研究、协调多个专业 Agent,最后汇总成结构化报告——整个过程不需要用户逐步指导。这才是 Agentic 应用的核心价值。
六、从单机到多机:Lane 队列的价值
上面构建的是单机版本。当你的产品需要处理更复杂的场景时——比如同时服务多个用户、或者把计算密集型任务分发到远程机器——Lane 队列提供了解决方案。
Lane 队列把工具调用按优先级分为四个通道:
Control (P0) ← 控制指令,最高优先级,顺序执行
Query (P1) ← 读文件、搜索,并行执行
Execute (P2) ← 写文件、运行命令,顺序执行
Generate(P3) ← LLM 调用,最低优先级
Query 通道的并行执行是关键优化:当 LLM 在一个轮次里返回多个读文件请求时,它们会并行执行,而不是串行等待。
import { SessionQueueConfig } from '@a3s-lab/code';
const session = agent.session(process.cwd(), {
queueConfig: {
enableAllFeatures: true,
queryMaxConcurrency: 8, // 最多 8 个读操作并行
},
});
当你需要把执行任务分发到远程机器时:
// 把 Execute 通道切换为外部模式
await session.setLaneHandler('execute', {
mode: 'external',
timeoutMs: 120_000,
});
// 监听外部任务,分发给 Worker
const events = await session.stream('运行完整的测试套件并修复所有失败');
for await (const event of events) {
if (event.type === 'external_task_pending') {
const tasks = await session.pendingExternalTasks();
for (const task of tasks) {
// 发送给远程 Worker(你的传输层:gRPC、HTTP、消息队列等)
const result = await dispatchToWorker(task);
await session.completeExternalTask(task.task_id, result);
}
}
}
这个模式让你可以在不修改 Agent 逻辑的前提下,把计算密集型任务透明地分发到任意数量的远程机器。
七、为什么 A3S Code 是构建 Agentic 应用的最佳选择?
构建真正具备 Agentic 特性的应用,需要三个条件同时满足。
第一:自主执行循环。 Agent 必须能够感知、决策、行动、验证,形成闭环,不依赖人类逐步指导。这要求底层框架提供稳定的 AgentLoop 驱动机制,以及可靠的工具执行和并发控制。A3S Code 的极简核心(5 个组件)专门为此设计——Lane 队列保证执行顺序,Query 通道并行读取,Execute 通道顺序写入,Generate 通道管理 LLM 调用。
第二:完整的上下文工程能力。 Agent 在每个轮次都需要恰好足够的信息——不多也不少。这不是一个单点问题,而是需要多个机制协同:
ContextProvider实现渐进式披露,按需检索,不需要预先向量化整个知识库MemoryStore保留跨会话的关键发现,避免重复探索ContextCompactor在 token 超限时自动压缩,保留语义关键信息
三者共同构成完整的上下文工程体系。没有任何一个单独的 RAG 库或记忆系统能替代这套协同机制。
第三:可嵌入、可扩展、生产可用。 Agentic 能力必须能作为基础设施嵌入你的产品,而不是锁定在某个 CLI 工具里。A3S Code 是 Rust 核心库,提供 Node.js 和 Python 原生绑定:
- 19 个 trait 扩展点,任何部分都可以替换,核心保持稳定
- 多租户支持,同一个 Agent 实例可以服务多个用户
- 多机器任务分发,Execute Lane 可以透明地路由到远程 Worker
- A3S Box 集成,代码执行天然隔离在 MicroVM 沙箱
这三个条件,A3S Code 是目前唯一同时满足的开源框架。从文章开头的 20 行代码,到多机器分布式执行系统,用的是同一套 API。
八、结论
Agentic AI 的核心是感知—决策—行动的闭环,编码任务是这个闭环的最高密度测试场。
构建可靠的 Agentic AI 系统,需要遵循两个核心原则:
极简核心——系统的不可替换部分应该尽可能小,只包含驱动 LLM 轮次所必需的组件。
工具自举——所有扩展能力通过工具实现,LLM 是最好的工具路由器,核心代码保持不变。
从文章开头的 20 行代码,到多机器分布式执行系统,A3S Code 的 API 始终如一。这就是极简核心的价值:核心稳定,能力无限扩展。
A3S Code 是开源的 Rust 编码 Agent 框架,提供 Rust、Node.js、Python SDK。查看文档 · GitHub