# 传入上下文 (/docs/developers/agent/embed/context)



把当前课程、选中的订单或用户偏好交给智能体，让回答贴合用户此刻的任务。页面状态用 readables 随消息发送；后端核实的信息用宿主上下文传入。

## 准备接入 [#prepare]

准备一个已能回复的 Kit 页面、服务智能体和嵌入策略。下面的 HTML 由你的宿主网站提供；同源 `POST /api/praxis-token` 是你按[嵌入令牌与用户](/docs/developers/agent/embed/tokens)实现的后端路由，验证登录态后返回 `{ token }`，不是 Praxis 的公开接口。示例使用 Develop 的 Kit 和 API，页面来源须已获准接入。

## 随消息传入页面状态 [#page-context]

把下面的页面保存为网站中的 HTML。下拉框变化时更新登记值，发送消息时 Kit 取当前快照。

```html
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8" />
<title>课程助手</title>
<label>当前课程
  <select id="lesson">
    <option value="第三课：配送规则">第三课：配送规则</option>
    <option value="第四课：退货流程">第四课：退货流程</option>
  </select>
</label>
<button id="clear">停止传入课程</button>
<praxis-agent style="display:block;height:600px"></praxis-agent>
<script type="module">
  import "https://kit-develop.praxisusercontent.com/v1/praxis-kit.js";
  await customElements.whenDefined("praxis-agent");
  const chat = document.querySelector("praxis-agent");
  const lesson = document.querySelector("#lesson");
  const update = () => chat.setReadable("lesson", { title: lesson.value });
  update();
  lesson.addEventListener("change", update);
  document.querySelector("#clear").addEventListener("click", () => {
    chat.removeReadable("lesson");
  });
  chat.addEventListener("praxis.log", event => console.warn(event.detail));
  chat.setOptions({
    api: {
      url: "https://api-develop.deepraxis.com",
      getToken: async () => {
        const response = await fetch("/api/praxis-token", {
          method: "POST", credentials: "same-origin",
        });
        if (!response.ok) throw new Error(`Token request failed: ${response.status}`);
        const { token } = await response.json();
        if (typeof token !== "string" || !token) throw new Error("Missing token");
        return token;
      },
    },
    agent: { name: "课程助手" },
  });
</script>
</html>
```

**预期结果：** 询问「我正在看哪一课」，智能体收到第三课的信息；切换课程再发消息，新消息携带第四课。点击「停止传入课程」后，后续消息不再附带该项。

`setReadable(name, value)` 接受字符串或可 JSON 序列化的值；名称须匹配 `[A-Za-z0-9_.:-]{1,64}`。同名登记覆盖当前值，`removeReadable(name)` 删除登记。非法名称、不能序列化的值会抛错，原登记保持不变。

每条消息最多 32 项，整个上下文 JSON 最多 4096 UTF-8 字节。超出时 Kit 从最早登记的项开始丢弃本次快照中的数据，并通过 `praxis.log` 发出 `warn`，`data.names` 列出丢弃项。登记本身保留；缩小值后可再次发送。

页面上下文附在本轮用户消息里，标记为不可信。每轮取新快照，但移除登记不会抹去旧消息中的信息。它不能证明用户身份、账户余额或订单归属。

## 传入后端核实的信息 [#host-context]

在宿主后端签发令牌时传 `system_message`。下面是服务端请求：替换公开智能体 ID，测试用户 ID 换成宿主登录态确定的 ID；不要把 `PRAXIS_API_KEY` 或这段命令放进网页。

```bash
curl --fail-with-body https://api-develop.deepraxis.com/agent/v1/embed_tokens \
  -X POST \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "agent": "agent_example",
    "external_user_id": "customer_123",
    "system_message": [{"type": "text", "text": "客户偏好中文回复。"}]
  }'
```

**预期结果：** 响应为 HTTP 201，包含 `token`、`id` 和 `expires_at`。让宿主路由只把所需的短期凭据返回浏览器，用该令牌创建新会话，用户偏好会进入模型上下文。不要把令牌打印到共享日志。

`system_message` 是 `{ type: "text", text }` 数组，文本合计最多 8192 UTF-8 字节；使用一个文本块可避免分块分隔符增加体积。它是模型可读信息，不是秘密存储。

已经开始的会话可以由 API Key 持有者通过[发送事件](/docs/api/native/agent/sendEvents)追加 `system.message`；更换令牌不会改写已建立会话的上下文。

## 选择其他输入 [#choose-input]

| 需要传入的内容         | 使用方式                                                              |
| --------------- | ----------------------------------------------------------------- |
| 每位用户都相同的角色和语气   | 控制台「配置 → 指令」                                                      |
| 只对一张令牌更换整套指令    | 签发时传 `agent_override.system`；须先在「配置 → 安全」开启「允许宿主覆盖指令」；`null` 清空指令 |
| 只在被问及时读取的页面数据   | [前端工具](/docs/developers/agent/embed/client-tools)                 |
| 订单等需要鉴权或最新查询的数据 | 服务端工具，按终端用户限定数据范围                                                 |

覆盖未获准时返回 HTTP 400、`EMBED_FIELD_NOT_ALLOWED`。先修正策略或去掉覆盖字段，再重新签发；重复同一请求不会解除限制。

## 验证传入结果 [#verify]

打开浏览器 Network，发送消息，检查请求中的 `praxis_context.items`：应有 `name: "lesson"` 和当前课程的字符串值。切换课程、删除登记后各发一次，确认请求随之变化；不要只凭模型回答判断是否传入成功。

后端上下文用新签发的令牌新建会话，询问回复语言并核对签发请求中的文本。模型回复用于体验验证；身份和权限仍由宿主后端及工具服务端校验。

下一步：[前端工具](/docs/developers/agent/embed/client-tools) · [保护嵌入接入](/docs/developers/agent/embed/security) · [智能体 API](/docs/api/native/agent)。
