---
type: study
created: 2026-08-11
updated: 2026-08-11
sensitivity: private
status: active
tags:
  - study
  - langchain
  - managed-deep-agents
  - typescript
  - security
topic: Managed Deep Agents TypeScript 扩展能力与安全边界
sources:
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-tools
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-mcp-connectors
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-middleware
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-memory
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-sandboxes
  - https://docs.langchain.com/langsmith/javascript/managed-deep-agents-identity
last_verified: 2026-08-11
---

# Managed Deep Agents TypeScript：扩展能力与安全边界

## 结论先行

TypeScript 版把 authored tools、MCP、middleware、memory、sandbox 和 identity 分成不同的扩展面。它们可以组合，但不能互相替代：sandbox 提供隔离环境，不提供业务授权；identity 证明调用者，不约束工具副作用；memory 跨线程持久化知识，却必须被视为不可信输入。

生产安全必须同时覆盖身份、线程归属、工具审批、文件权限、远端工具 allowlist、超时、幂等、秘密路由和共享状态隔离。

## Authored tools 与 HITL

TypeScript authored tool 使用 LangChain `tool` 和 Zod schema 定义，放在 `tools/` 中，由 `agent.ts` 显式导入并加入 `tools` 数组。

```ts
export const lookupCustomer = tool(
  async ({ customerId }) => lookup(customerId),
  {
    name: "lookup_customer",
    description: "按 ID 查询客户",
    schema: z.object({ customerId: z.string() }),
  },
);
```

工程边界：

- authored tool 适合私有 API、数据库和项目内业务逻辑。
- 工具名必须清晰且唯一，避免与其他本地工具或 MCP 前缀后的名称碰撞。
- 外部写操作必须做输入校验、权限检查、幂等和可审计错误处理。
- 每次运行的用户、组织、feature flag 或请求 metadata 应通过 LangChain runtime context 传递，不应默认拼进模型 prompt。
- 部署 secret 可从环境变量读取，但不能把 key 记录到返回值、日志或 trace 内容中。

对敏感调用，在 agent definition 使用 `interruptOn`，让人类批准、编辑或拒绝；文件系统再叠加 `permissions`。托管 runtime 自带 durable checkpointer，暂停/恢复不需要项目自行配置状态存储。

本地中断通过 Studio 处理；部署后通过 LangGraph Server resume payload 恢复。当前 public beta 仍是 CLI-first，自有应用的完整 programmatic invocation 未正式文档化，不能在未确认接口契约时设计关键业务流程。

## MCP connectors

`connectors/mcp.ts` 必须导出命名 `connector`，通过 `connectors.mcp({ mcpServers: ... })` 声明远端服务器。

| 维度 | TypeScript 规则 |
| --- | --- |
| Transport | Streamable HTTP 与 legacy SSE；不支持 stdio |
| 工具选择 | 默认全量；生产优先 `includeTools` allowlist，可再用 `excludeTools` |
| 名称 | 选择时使用原始 MCP 名，加载后默认加 `{server}__` 前缀 |
| 失败策略 | `throwOnLoadError` 默认 `true`，即 fail closed |
| HTTP 兼容 | 可配置 `automaticSSEFallback` |
| 调用超时 | `defaultToolTimeout` 的 TypeScript 单位是毫秒 |
| 凭据 | 从环境变量构造 headers，禁止硬编码 |

与 Python 的高风险差异是超时单位：同一个数值在 Python 表示秒，在 TypeScript 表示毫秒。迁移配置时必须按单位换算，否则会出现极短超时或意外长时间占用资源。

文档表格同时列出 snake_case 与 camelCase 别名；TypeScript 新代码应使用 `includeTools`、`excludeTools`、`defaultToolTimeout`、`automaticSSEFallback`、`prefixToolNameWithServerName` 和 `throwOnLoadError`，避免跨语言配置混杂。

远端 MCP 是供应链和授权边界：只暴露必要工具，限制请求时间，验证 endpoint 与 TLS，决定连接失败是阻断启动还是显式降级，并对每个有副作用的 MCP tool 施加业务级授权。

## Middleware

TypeScript 可以直接使用 LangChain 预构建 middleware，也可以用 `createMiddleware` 定义 `wrapToolCall` 等 hook。数组顺序就是组合顺序，应把数据清洗、限额、重试、fallback、审计和监控的先后关系显式化。

```ts
export const logToolCalls = createMiddleware({
  name: "LogToolCalls",
  wrapToolCall: async (request, handler) => {
    const result = await handler(request);
    return result;
  },
});
```

TypeScript wrapper 应正确 `await` 下游 handler，保持异常和取消语义；不能在日志中输出完整参数、模型输入或 secret。运行时仍由 MDA 管理 backend、store、checkpointer、memory、skills 和 system prompt，middleware 不应重新实现这些能力。

常见推荐顺序不是固定公式，但必须验证：

1. 身份/上下文校验。
2. 输入 PII 处理和 guardrail。
3. 调用限额与预算。
4. 重试或模型 fallback。
5. 工具前授权与审计。
6. 输出清洗和可观测性。

## Durable memory

默认只有 thread/session 级状态。跨线程 durable memory 需要根目录 `memory.ts` 显式启用：

```ts
export const memory = defineMemory({ scope: "agent" });
```

也可以用 `scope: "none"`，或删除声明关闭。启用后，Context Hub 的 `memories/agent` 挂载为 `/memories/agent/`：

- `/memories/agent/AGENTS.md` 是每次运行加载的 hot memory，必须短小。
- 同一树中的其他文件是按需读取的 cold memory。
- 只有该树内的写入会持久化；写到别处不等于 durable memory。
- 部署同步 instructions/skills 时，不会覆盖已经保存的 durable memory。

最高风险在于 `scope: "agent"` 是 deployment-wide：每个调用者都能影响后续调用者读取的内容。Memory 必须当作不可信笔记，不能授予权限、修改审批、覆盖 agent definition 或存储个人数据、客户私有数据、Token、API key 和其他秘密。调用者不应互相影响时，不要启用这种共享 memory。

## Sandbox

TypeScript sandbox 位于 `sandbox/index.ts`，用 `defineSandbox` 声明。目录存在才启用；删除 `sandbox/` 即退出该能力。

| 字段 | 含义 | 生产建议 |
| --- | --- | --- |
| `scope: "thread"` | 每个 durable thread 一个 sandbox，并跨该线程运行复用 | 默认选择 |
| `scope: "agent"` | Agent 进程处理的线程共享文件 | 仅显式共享场景 |
| `idleTtlSeconds` | 空闲多久后允许回收 | 控制成本与复用窗口 |
| `defaultTimeout` | 单条命令最大执行时间 | 限制资源占用 |
| `templateName` / `snapshotId` | sandbox 创建来源 | 两者只能选一个 |

Agent 可使用文件工具和 `execute`。Instructions 应限定工作目录和禁止修改的路径，但 prompt 约束不能替代平台隔离与应用权限。

Sandbox 不是授权模型，也不是跨用户数据隔离的自动证明。仍需路径权限、工具审批、资源限制、网络策略、输入校验和审计。`agent` scope 会让不同线程读写同一文件，默认应视为跨租户泄露风险。

## Identity

| 目标 | TypeScript 声明 | 安全边界 |
| --- | --- | --- |
| SDK、脚本、服务访问 | `auth.langsmithApiKey()` | 只控制能否访问，不能自动隔离最终用户线程 |
| 登录用户私有会话 | `auth.supabase({ projectRef })` | 用 verified JWT 建立 thread ownership |

默认模式要求客户端发送 `x-api-key`。任何持有 workspace key 的人都可访问 deployment，因此它是服务凭据，不是 end-user identity。

Supabase 模式支持 `projectRef` 或自定义 auth `url`。浏览器只应持有 Supabase publishable key，并在每次请求发送 `Authorization: Bearer <access_token>`；绝不能把 LangSmith API key 下发到客户端。MDA 根据项目 JWKS 验证 JWT。

已有 deployment 后切换 Supabase，不会自动为历史 thread 补 owner metadata。必须设计迁移，并验证：

- 无凭据或无效 token 返回 401。
- 同一用户能继续自己的 thread。
- 跨用户访问返回 403。
- 历史 thread 不会因缺少 owner 而被错误共享或永久锁死。

## 上线安全清单

- Authored tool 对副作用实现幂等、业务授权、输入校验和 HITL。
- MCP 使用 allowlist、毫秒级超时、唯一前缀和明确的加载失败策略。
- Middleware 顺序、Promise/异常传播、PII 脱敏和日志字段经过测试。
- Memory 明确 caller 隔离模型，禁止把共享内容当作可信指令。
- Sandbox 默认 thread scope；本地 fallback 与线上 managed sandbox 分别验证。
- Supabase 覆盖 401、同用户、跨用户 403 与历史 thread 迁移。
- 浏览器、日志、trace、Context Hub 和 memory 中都不出现 LangSmith key 或 provider secret。

## 关联

- [[01-TypeScript架构与项目模型|TypeScript 架构与项目模型]]
- [[03-TypeScript渠道调度与评估|TypeScript 渠道、调度与评估]]
- [[04-TypeScript本地开发部署与CLI|TypeScript 本地开发、部署与 CLI]]
