`ctx` 对象在 `Create` 和 `Next` Hook 中均可使用,提供消息发送、记忆、追踪、工具调用和 Agent 间通信能力。
## 属性
```typescript
ctx.chat_id // 当前会话 ID
ctx.assistant_id // 当前 Assistant 的 ID
ctx.locale // 用户语言,如 "en-us"
ctx.route // 请求路由(URL 路径 + 查询参数)
ctx.metadata // 元数据 Map —— 由调用方或 Create Hook 的 metadata 返回值设置
ctx.authorized // 认证信息:{ user_id, team_id, ... }
ctx.authorized?.user_id // 当前用户 ID
ctx.authorized?.team_id // 当前团队 ID
```
## 消息发送
### 发送消息
```typescript
ctx.Send("Hello!"); // 文本简写
ctx.Send({ type: "text", props: { content: "Hello!" } });
ctx.Send({ type: "error", props: { message: "Failed", code: "E001" } });
```
### 流式输出
```typescript
const msgId = ctx.SendStream({ type: "text", props: { content: "" } });
ctx.Append(msgId, "Step 1... ");
ctx.Append(msgId, "Step 2... ");
ctx.End(msgId);
```
### 更新流式消息
```typescript
const msgId = ctx.SendStream({ type: "loading", props: { message: "加载中..." } });
// ... 执行任务 ...
ctx.Replace(msgId, { type: "text", props: { content: "完成!" } });
ctx.End(msgId);
```
### Merge / Set 字段
```typescript
const msgId = ctx.SendStream({ type: "status", props: { progress: 0 } });
ctx.Merge(msgId, { progress: 50 }, "props");
ctx.Merge(msgId, { progress: 100, done: true }, "props");
ctx.End(msgId);
// 设置特定字段
ctx.Set(msgId, "success", "props.status");
```
### 消息分组(Block / Thread)
```typescript
const blockId = ctx.BlockID();
ctx.Send("步骤 1", blockId);
ctx.Send("步骤 2", blockId);
ctx.EndBlock(blockId);
```
## Memory(记忆)
四个命名空间,各有不同的生命周期 —— 详见 [Memory](./memory) 页面。
| 命名空间 | 作用域 | 存活时间 |
|----------|--------|---------|
| `ctx.memory.context` | 当前请求 | 仅限 Create → Next |
| `ctx.memory.chat` | 当前会话 | 直到会话结束 |
| `ctx.memory.user` | 每个用户 | 永久 |
| `ctx.memory.team` | 每个团队 | 永久 |
```typescript
ctx.memory.context.Set("key", value);
const v = ctx.memory.context.Get("key");
```
## MCP
在 Hook 中手动调用 MCP 工具(而非让 LLM 自动调用):
```typescript
// 调用单个工具
const result = ctx.mcp.CallTool("server-id", "tool-name", { arg: "value" });
// 在同一 Server 上顺序调用多个工具
const results = ctx.mcp.CallTools("server-id", [
{ name: "tool1", arguments: { a: 1 } },
{ name: "tool2", arguments: { b: 2 } },
]);
// 在同一 Server 上并行调用多个工具
const results = ctx.mcp.CallToolsParallel("server-id", [
{ name: "tool1", arguments: { a: 1 } },
{ name: "tool2", arguments: { b: 2 } },
]);
// 跨 Server 并行调用 —— 等待全部完成
const results = ctx.mcp.All([
{ mcp: "server1", tool: "search", arguments: { q: "query" } },
{ mcp: "server2", tool: "fetch", arguments: { id: 1 } },
]);
// 跨 Server —— 第一个成功的结果胜出(其余取消)
const result = ctx.mcp.Any([...]);
// 跨 Server —— 第一个完成的结果胜出(不论成功或失败)
const result = ctx.mcp.Race([...]);
```
## Search(搜索)
在 Hook 中触发搜索:
```typescript
const web = ctx.search.Web("query", { limit: 10 });
const kb = ctx.search.KB("query", { collections: ["docs"], threshold: 0.7 });
const db = ctx.search.DB("query", { models: ["model.name"] });
// 并行 —— 等待全部完成
const results = ctx.search.All([
{ type: "web", query: "topic" },
{ type: "kb", query: "topic", collections: ["docs"] },
]);
// 第一个成功的胜出(其余取消)
const result = ctx.search.Any([...]);
// 第一个完成的胜出
const result = ctx.search.Race([...]);
```
## Agent(A2A)
将另一个 Agent 作为函数调用。被调用的 Agent 运行在**独立上下文**中,不共享对话历史,结果返回给调用方的 Hook。
```typescript
// 基本调用
const result = ctx.agent.Call("assistant-id", messages);
// 带流式回调
const result = ctx.agent.Call("assistant-id", messages, {
onChunk: (msg) => {
ctx.Send(msg); // 将 chunk 转发给客户端
return 0; // 0 = 继续
},
});
// 并行调用 —— 等待全部完成
const results = ctx.agent.All([
{ agent: "agent-1", messages, options: {} },
{ agent: "agent-2", messages },
]);
// 第一个成功的胜出
const result = ctx.agent.Any([...]);
// 第一个完成的胜出
const result = ctx.agent.Race([...]);
```
共享历史的路由请使用 Hook 返回值中的 `delegate` —— 见[多 Agent 协作](./multi-agent)。
## LLM
直接调用 LLM,不经过 Agent 流水线。所有方法均为流式,通过 `onChunk` 回调接收输出:
```typescript
// 单个 connector
const result = ctx.llm.Stream("gpt-4o", messages, {
onChunk: (msg) => {
ctx.Send(msg); // 转发给客户端
return 0; // 0 = 继续,非零 = 停止
},
});
// 多个 connector 并行 —— 等待全部完成
const results = ctx.llm.All([
{ connector: "gpt-4o", messages, options: { temperature: 0.5 } },
{ connector: "claude-3", messages },
]);
// 多个 connector —— 第一个成功的胜出(其余取消)
const result = ctx.llm.Any([...]);
// 多个 connector —— 第一个完成的胜出(不论成功或失败)
const result = ctx.llm.Race([...]);
```
## Trace(追踪)
记录可在 Agent 追踪视图中查看的调试节点:
```typescript
const node = ctx.trace.Add(
{ input: "data" },
{ label: "Processing", description: "Parsing user input" }
);
node.Info("步骤已开始");
node.SetOutput({ result: data });
node.Complete({ status: "done" });
// 或 node.Fail("Error message");
// 顶层日志(无节点)
ctx.trace.Info("开始处理...");
ctx.trace.Error("出现错误");
```
## 沙箱(CLI Agent)
仅在配置了 `sandbox` 时可用 —— 在 CLI Agent 章节介绍。
```typescript
ctx.sandbox.ReadFile("output.json");
ctx.sandbox.WriteFile("input.txt", content);
ctx.sandbox.Exec(["npm", "test"]);
```
关于 `ctx.workspace` 文件系统访问和 `ctx.computer` 容器操作,请参阅 [Workspace API](/tutorials/agent/cli-agent/workspace) 页面。
## 下一步
Memory 在真实 Agent 中大量使用,值得单独一页详细介绍。
→ **[Memory](./memory)**