关于 managed-deep-agents
Managed Deep Agents 是通过 LangSmith 部署 Python 或 TypeScript Deep Agents 的托管运行时。它将基于目录的项目与命令行工作流结合,并提供持久运行、记忆、追踪和沙箱等托管基础设施。
主要功能
- 01Python 和 TypeScript Agent 项目
- 02使用 mda dev 本地开发
- 03通过 mda deploy 或 GitHub 部署
- 04托管运行、记忆和追踪
- 05Context Hub 提示词与技能
- 06远程 MCP 服务声明
适用场景
- 01在 LangSmith 部署代码编写的 Deep Agent
- 02部署前本地测试 Agent
- 03为 Agent 添加远程 MCP 服务
- 04运行定时任务或连接 Slack 的 Agent
MCP 相关
Agent 可在 tools/mcp.py 或 tools/mcp.ts 中声明远程 MCP 服务,运行时会将其作为 Agent 工具提供。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ langchain-ai/ langchain-skills --skill managed-deep-agents安装后在 Claude Code 中输入/managed-deep-agents确认已加载。
详细介绍
托管式 Deep Agents
概述
托管式 Deep Agents(MDA)是 LangSmith 中面向代码优先型 Deep Agents 的托管运行时。你可以用 Python 或 TypeScript 编写 Agent,使用 mda dev 在本地测试,然后通过 mda deploy 部署,或从 LangSmith 中已连接的 GitHub 仓库部署。它将开源 Deep Agents 执行框架(参见 [[deep-agents-core]])与托管基础设施相结合:持久化运行、沙盒、由 Context Hub 提供支持的指令和技能、记忆、追踪记录,以及托管式 LangGraph 部署。
核心理念是:Agent 是一个目录。文件的位置决定其作用,CLI 会将该目录编译为托管式 LangGraph 应用。
MDA 目前处于公开测试版,且仅运行于 US LangSmith Cloud。
适用场景
当用户希望用代码构建 Deep Agent,并在 LangSmith 上运行而无需自行运维服务器时,或者希望为 Agent 添加工具、MCP 服务、连接、middleware、记忆、身份、计划任务、通道、技能、沙盒或评估时,请使用此技能。
如果用户需要在 Agent 部署中自定义服务器路由或运行时接线、更强的隔离能力、最高可扩展性,或需要使用 US 以外的区域,则应改用标准 LangSmith Deployment(参见 [[langgraph-cli]]、langgraph deploy)。MDA 仍可部署在单独运维的后端之后,由该后端对调用方进行身份验证,并代理可信身份标头。
引导用户构建他们的第一个 Agent
当用户刚开始使用 MDA,或提出类似“帮我构建一个 Agent”的请求时,不要立即搭建脚手架。请按此流程进行。这只需询问两个问题,就能避免构建出平台无法托管的内容。
ask what they want to build -> check it against the limits -> confirm the shape
-> scaffold -> wire the smallest thing that runs -> mda dev -> deploy
1. 询问他们想构建什么
用通俗的语言提问,不要使用 MDA 术语。用户还不知道“通道”或“沙盒”是什么。
首先询问以下两点:
- Agent 应该做什么?(“回答有关我们文档的问题”“整理收到的 bug”“每天早上发布一份摘要”。)
- 谁或什么会与它交互,从哪里交互?(用户在浏览器中使用、用户应用的用户使用、某个 Slack 工作区使用、无人使用——它按计时器运行。)
然后,只询问答案实际引出的后续问题:
- 它是否需要在不同对话之间记住内容?
- 它是否需要访问私有 API、数据库或内部服务?
- 是否需要在执行某些操作前由人工审批?
- 它是否需要写入文件或运行代码?
一旦你能够确定所需能力,就停止提问。通常问两三个问题就够了。
2. 根据限制检查答案
在承诺任何事情之前,请根据下文的**MDA 无法实现的功能**检查请求。如果请求的某部分超出范围,请用一句话说明,提供最接近的受支持方案,并继续处理其余部分。不要悄悄构建一个功能更少的 Agent,却把它说成用户要求的内容。
常见的引导方向:如果用户需要自定义 HTTP 路由、自有身份验证,或非 US 区域托管,请告知他们 MDA 并非合适的层,并指向 langgraph deploy([[langgraph-cli]])。
3. 将答案映射到相应能力
| 用户描述的需求 | 应该选择的方案 | 所在位置 |
|---|---|---|
| 它应该如何表现、采用什么语气、遵循哪些规则 | 指令 | instructions.md |
| 调用我们的 API/数据库/内部服务 | 自定义工具 | tools/ |
| 使用远程 MCP 服务 | MCP 声明 | tools/mcp.py 或 tools/mcp.ts |
| 使用工作区密钥或 OAuth 授权 | 连接 | connections.get(...) + mda connections |
| 它应遵循的特定任务流程 | 技能 | skills/<name>/SKILL.md |
| 在对话之间记住信息 | 持久记忆(请阅读警告) | memory.py |
| 按定时器运行,无用户消息触发 | 定时任务 | schedules/<name>.py |
| 运行在 Slack 中 | 渠道 | channels/slack.py |
| 写入文件、运行代码或 shell 命令 | 沙箱 | sandbox/__init__.py |
| 执行 X 前先询问我 | 人机协作 | interrupt_on= |
| 用户不得看到彼此的聊天记录 | Supabase 身份 | identity.py |
| 必须返回结构化数据,而非散文 | 结构化输出 | response_format= |
| 将专门的工作交给其他 Agent | 子 Agent | subagents= |
| PII 脱敏、调用限制、重试、日志记录 | 中间件 | middleware/ |
| 验证它在变更后仍能正常工作 | Harbor 评估 | evals/<task>/ |
4. 写入文件前先确认方案
用一段简短的话复述计划,并取得对方同意。写明模型,并且只列出你实际要创建的能力:
research-assistant, Python, on anthropic:claude-sonnet-4-6
instructions.md how it researches and cites
tools/search.py web search
schedules/ weekday 8am digest
no memory, no sandbox, no channel
5. 搭建并连接可运行的最小项目
使用与计划相符的标志进行搭建,这样项目一开始就是正确的,而不必之后再修改成合适的样子:
mda init research-assistant --model anthropic:claude-sonnet-4-6
cd research-assistant
uv sync
然后一次只添加一种能力,并在添加下一种之前确认每种能力都能正常工作。一个能根据完善的指令作答并使用一个真实工具的首版 Agent,比填满所有目录的脚手架更适合作为起点。
不要创建计划中未要求的目录。空置或未使用的 skills/、channels/ 或 schedules/ 目录只会增加杂乱;用户不需要的 sandbox/ 目录则会启用沙箱,让用户无缘无故地为此操心(mda init --no-sandbox 会跳过它)。
6. 处理密钥,但不要接触密钥值
mda init 会创建一个包含空占位符的 .env。填写项目所需的名称,并让用户粘贴值:
- 不要自行将有效凭据值写入
.env,也不要从其他项目目录复制密钥。 - 不要在终端或回复中回显密钥值。
- 确认
.gitignore已覆盖.env和.env.*——mda init已经完成此操作。
项目需要通过 LangSmith 身份验证才能部署,也需要所选模型要求的凭据。对于常规的提供商模型,取消对应密钥的注释(ANTHROPIC_API_KEY、OPENAI_API_KEY 等),并让用户通过 .env 或 LangSmith 工作区密钥提供它。显式配置的 Gateway 客户端使用其 Gateway/LangSmith 凭据,而不是提供商密钥。
7. 在本地运行,然后部署
mda dev . # compiles, opens LangSmith Studio, hot reloads
mda deploy . # syncs Context Hub, uploads, waits for DEPLOYED
部署前,让用户在 Studio 中实际发送一条消息,并确认 Agent 调用了工具。mda deploy 会输出部署控制面板 URL;打开该页面以检查构建、修订版本和跟踪记录。
MDA 无法实现的功能
在同意构建之前,先对照此列表检查请求。尽早坦诚说明限制,比等到部署时才发现要省事得多。
| 限制 | 后果 |
|---|---|
| 仅支持 US LangSmith Cloud | 不支持自托管、混合部署或 EU 区域。需要使用 langgraph deploy。 |
| 没有公开的管理 API | 使用 mda 或 LangSmith 的 GitHub 部署界面创建和更新 Agent。不要编造公开的创建/更新 REST 流程。 |
| 仅支持 Slack 渠道 | 不支持 Discord、Teams、电子邮件或 SMS 渠道。这些产品的远程 MCP 服务是工具,而不是渠道。 |
| 记忆在部署范围内共享 | 所有调用方共用一棵 /memories/agent/ 目录树。没有按用户划分的记忆。 |
| 每个项目只能有一个 Agent 入口 | 一个项目中不能有多个图。使用 subagents= 进行委派。 |
| 计划任务必须是静态字面值 | 计划任务声明中不能使用环境变量、函数调用或计算值。 |
| 构建归档上限为 200 MB | 项目中的大型 fixture 或模型权重会导致部署失败。 |
| 托管字段不可自行设置 | backend、store、checkpointer、memory、skills 和系统提示词由运行时注入。 |
| 沙盒范围由系统管理 | 每个线程对应一个沙盒。不再支持 Agent 共享沙盒范围。 |
前置条件
- 一个已获准使用 Managed Deep Agents 公测版的工作区,以及该工作区的 LangSmith API 密钥。
- Python 项目需要 Python 和
uv;TypeScript 项目需要 Node.js 和 npm。 - 所选模型所需的凭据,可放在项目
.env文件中,也可设为 LangSmith 工作区密钥。
安装 CLI。这两个软件包提供相同的 mda 二进制文件:
uv tool install --prerelease allow managed-deepagents # Python
npm install -g managed-deepagents@dev # TypeScript
mda init 会生成带有独立清单的项目——在运行 mda dev 之前,需在该项目目录中运行 uv sync(或 npm install)。
项目布局
传递给 mda 的路径就是项目根目录。文件的位置决定其作用:
my-agent/
agent.py | agent.ts # Required: exports the named `agent`
instructions.md # System prompt -> Context Hub
skills/<name>/SKILL.md # Task-specific procedures -> Context Hub
tools/ # Authored tools the agent imports
mcp.py | mcp.ts # Optional remote MCP server declaration
middleware/ # Authored middleware the agent imports
identity.py | identity.ts # Who may call the deployment
memory.py | memory.ts # Opt-in durable memory
channels/<name>.py # External messaging (Slack)
schedules/<name>.py # Managed cron schedules
sandbox/__init__.py | index.ts # Managed sandbox
pyproject.toml | package.json # Dependencies
.env # Auth + runtime secrets, never archived
evals/<task>/ # Harbor evals, not deployed
只有 Agent 入口是必需的。tools/ 和 middleware/ 只是常规目录——MDA 会原样复制项目文件,因此 Agent 导入的任何本地模块都能正常使用。其他路径在存在时会被赋予托管含义。TypeScript Agent 入口可以是 agent.ts 或 agent.tsx;发现托管辅助声明时,也接受 .mts 和 .cts。
定义 Agent
Agent 入口返回的是运行时之前的规范,而不是已编译的图。
# agent.py
from managed_deepagents import define_deep_agent
from tools.search import web_search
agent = define_deep_agent(
name="research-assistant",
model="anthropic:claude-sonnet-4-6",
tools=[web_search],
)
// agent.ts
import { defineDeepAgent } from "managed-deepagents";
import { webSearch } from "./tools/search";
export const agent = defineDeepAgent({
name: "research-assistant",
model: "anthropic:claude-sonnet-4-6",
tools: [webSearch],
});
name 为必填项。 传入一个以字母开头、且仅包含字母、数字、下划线或连字符的静态字符串。它会成为 LangGraph 助手 ID 和默认部署名称;使用 mda deploy --name 可覆盖默认部署名称。
作者可设置的字段: name、model、tools、middleware、subagents、permissions、interrupt_on / interruptOn、response_format / responseFormat、context_schema / contextSchema、cache、debug、metadata。
托管字段——请勿设置: backend、store、checkpointer、memory、skills、system_prompt / systemPrompt。
模型 ID 使用 {provider}:{model_id} 格式,并通过 init_chat_model 解析,因此其支持的任何提供商都可使用。请注意,不同语言使用的提供商标识不同:Python 使用 google_genai:gemini-3.6-flash,TypeScript 使用 google-genai:gemini-3.6-flash。如果需要在代码中配置模型参数,请传入聊天模型实例而不是字符串。
专用的 mda init --gateway 脚手架已移除。要使用 LangSmith Gateway,请在 agent.py 或 agent.ts 中显式配置受支持的聊天模型客户端;不要传入已移除的标志,也不要依赖它以前执行的凭据预检。
指令
项目根目录中的 instructions.md 是系统提示词。每次运行时都会插入该文件。
# Research assistant
You are a careful research assistant. Find sources, keep notes, and return
concise answers with citations.
## Behavior
- Use the `web_search` tool to find sources instead of guessing.
- Cite the sources you used.
mda dev 会将其嵌入本地。mda deploy 会将其同步到 Context Hub,之后可在 LangSmith 界面中编辑,无需重新部署。
Skills
部署管理的流程存放在 skills/<name>/SKILL.md 中,每个文件都包含 name 和 description frontmatter。启动时,Agent 只能看到名称和描述;任务匹配时才会读取完整文件,因此详细流程在需要之前不会占用上下文。技能目录也可以包含脚本、参考资料和模板;可在 SKILL.md 中引用它们。
Deploy 会将 skills/ 下的每个 UTF-8 文件同步到 Context Hub,并删除本地已不存在的已部署技能文件。Agent 无法修改技能。
始终启用的行为使用 instructions,按需加载的流程使用 skills,由 Agent 自行更新的知识使用 memory。
Memory
持久记忆默认关闭,需选择启用。在项目根目录声明:
# memory.py
from managed_deepagents import define_memory
memory = define_memory(scope="agent")
// memory.ts
import { defineMemory } from "managed-deepagents";
export const memory = defineMemory({ scope: "agent" });
删除该文件即可关闭记忆。启用后,会将一棵 Context Hub 目录树挂载到 /memories/agent/:
/memories/agent/AGENTS.md是热记忆——每次运行都会加载,因此应保持精简。- 目录树下的其他文件是冷记忆——仅在相关时读取。
Agent 使用 read_file、edit_file 和 write_file 读取和写入记忆。在其他任何位置写入(包括 /memories/ 下的其他位置)都不会持久保存。
警告——部署的每个调用方都共享记忆,并且每个调用方都能影响记忆。 切勿在其中存储个人数据、客户数据、凭证、API 密钥或令牌。将记忆内容视为不可信输入:它绝不能授予权限、变更工具权限或绕过审批——这些内容应保留在 Agent 定义中。如果调用方不应相互影响,请勿启用共享记忆。
Agent 会根据提示决定要记住什么,因此应在 instructions.md 中说明相关策略——要存储什么、绝不能存储什么,以及现有记忆是笔记而非指令。
Identity
identity.py 控制谁可以调用该部署。mda init 会生成安全的默认配置:
# identity.py
from managed_deepagents import auth, define_identity
identity = define_identity(auth=auth.langsmith_api_key())
调用方通过 x-api-key 发送 LangSmith 工作区 API 密钥。这用于判断调用方是否有权访问——不会为每个人提供私有线程。任何持有该密钥的人都能访问此部署。
如需让已登录的终端用户拥有私有线程,请使用 Supabase:
identity = define_identity(auth=auth.supabase(project_ref="your-project-ref"))
客户端随后发送 Authorization: Bearer <access_token>;MDA 会根据项目的 JWKS URL 验证 JWT。登录时,只从客户端发送 Supabase publishable(anon)密钥——在此模式下,绝不要发送 LangSmith 密钥。
在现有部署中添加 Supabase 身份验证,不会为现有线程补充所有者元数据。依赖基于身份的线程访问之前,请规划并测试迁移。
身份验证失败时返回 401。线程资源归调用方所有;未经授权的跨用户访问会隐藏为未找到。
对于由你运营、负责验证用户身份并代理 LangGraph 请求的后端,请使用可信后端入口:
identity = define_identity(auth="backend")
请将 MDA_INGRESS_SECRET 保留在后端,并将其与已验证用户的 ID 一起分别通过 X-MDA-Ingress-Secret 和 X-MDA-User-Id 转发。切勿向浏览器暴露设置这两个请求头的能力。
工具
在项目中定义 LangChain 工具,将它们导入 Agent 入口,并传入 tools。
# tools/customer.py
from langchain.tools import tool
@tool(parse_docstring=True)
def lookup_customer(customer_id: str) -> str:
"""Look up a customer record by ID.
Args:
customer_id: Customer ID from the CRM.
"""
return f"Customer {customer_id} is on the enterprise plan."
// tools/customer.ts
import { tool } from "langchain";
import { z } from "zod";
export const lookupCustomer = tool(
async ({ customerId }) => `Customer ${customerId} is on the enterprise plan.`,
{
name: "lookup_customer",
description: "Look up a customer record by ID.",
schema: z.object({ customerId: z.string().describe("Customer ID from the CRM.") }),
},
);
导入方式与普通本地项目完全相同。使用清晰且唯一的工具名称,以避免冲突。工具从环境变量读取部署密钥;本地值请放在 .env 中。对于请求元数据或功能标志等每次运行的值,请使用常规的 LangChain 运行时上下文 API。
在支持的情况下,可以内联传入提供商的服务端工具——例如,OpenAI 的 tools=[{"type": "web_search"}],这样就无需额外的 API 密钥。
工具和中间件通过 TypeScript 中的 runtime.serverInfo?.principal 或 Python 中的 runtime.server_info.principal 读取已解析的调用方。此前的 runtime.identity 接口没有兼容层。电子邮件和群组信息位于 principal.claims 下;渠道来源信息位于 serverInfo.source / server_info.source 下。
MCP 服务与连接
在 tools/mcp.py 或 tools/mcp.ts 中声明远程 MCP 服务。不要将声明导入 agent.py,也不要手动添加其工具;MDA 会发现名为 mcp 的导出项并挂载这些服务。
# tools/mcp.py
from managed_deepagents import connections, define_mcp
mcp = define_mcp(
servers={
"langchainDocs": {
"transport": "http",
"url": "https://docs.langchain.com/mcp",
"include_tools": ["search_docs_by_lang_chain"],
},
"notion": {
"transport": "http",
"url": "https://mcp.notion.com/mcp",
"connection": connections.get("notion", {"type": "user"}),
},
}
)
// tools/mcp.ts
import { connections, defineMcp } from "managed-deepagents";
export const mcp = defineMcp({
servers: {
langchainDocs: {
transport: "http",
url: "https://docs.langchain.com/mcp",
includeTools: ["search_docs_by_lang_chain"],
},
notion: {
transport: "http",
url: "https://mcp.notion.com/mcp",
connection: connections.get("notion", { type: "user" }),
},
},
});
connectors.mcp(...)、connectors/mcp.* 和 mcpServers / mcp_servers 是 0.7.x 中已弃用的兼容别名,并将在 0.8.0 中移除。新开发请严格按照示例使用 defineMcp / define_mcp、tools/mcp.*、名为 mcp 的导出项以及 servers。
连接是按工作区限定的、不透明密钥或 OAuth 注册项,通过 slug 引用。connections.get(slug, { type: "user" }) 会解析每位调用方的 OAuth 或不透明凭据;当前 CLI 会创建归用户所有的 OAuth 槽位,而非归用户所有的不透明槽位。仅当每次运行都应使用同一个由 Agent 所有的密钥或授权时,才使用 { type: "agent" }。管理连接时请勿打印其值:
mda connections catalog
mda connections catalog --json
mda connections create acme-api --secret-from-env ACME_API_KEY
mda connections create notion --mcp https://mcp.notion.com/mcp
mda connections create github --oauth github --client-id "$GITHUB_CLIENT_ID" --secret-from-env GITHUB_CLIENT_SECRET --authorize
mda connections list
对于归用户所有的 OAuth,请省略 --authorize;运行时会在需要时请求每位调用方授权。--authorize 会登录一次以获取归 Agent 所有的授权,连接声明必须选择 { type: "agent" } 才能使用该授权。如果恰好有一个服务引用了该 slug,mda deploy 可以推断并创建缺失的、归用户所有的 MCP OAuth 注册项。在 mda dev 中,归用户所有的授权通过 Agent Auth 解析;Studio 需要个人 LangSmith 密钥或浏览器登录。其他服务主体无法拥有用户 OAuth 授权。归 Agent 所有的不透明连接通过 MDA_DEV_<SLUG> 解析。
OAuth 目录提供提供商端点、方法、默认作用域和授权参数,但不提供应用的客户端凭据。可使用 --auth-method、可重复使用的 --scope / --allowed-scope 以及 --authorization-param 覆盖默认设置;--scope 会替换目录默认值,而不是在其基础上追加。
中间件
中间件用于包装模型调用、工具调用和生命周期钩子。顺序由列表明确指定;MDA 不会推断顺序。请使用预构建的 LangChain 中间件或自行编写(参见 [[langchain-middleware]])。
from langchain.agents.middleware import ModelCallLimitMiddleware, PIIMiddleware
from managed_deepagents import define_deep_agent
agent = define_deep_agent(
name="support-agent",
model="anthropic:claude-sonnet-4-6",
middleware=[
PIIMiddleware("email", strategy="redact", apply_to_input=True),
ModelCallLimitMiddleware(run_limit=50),
],
)
中间件适用于处理个人身份信息、速率限制、重试、模型回退、动态模型选择和工具调用监控。
沙箱
沙箱为 Agent 提供隔离的文件系统和 Shell。mda init 会为其生成初始结构;删除 sandbox/ 目录即可选择不使用沙箱,适合只需要提示词、工具和记忆的 Agent。
# sandbox/__init__.py
from managed_deepagents import define_sandbox
sandbox = define_sandbox(
idle_ttl_seconds=600,
default_timeout=600,
)
// sandbox/index.ts
import { defineSandbox } from "managed-deepagents";
export const sandbox = defineSandbox({
idleTtlSeconds: 600,
defaultTimeout: 600,
});
沙箱按持久化线程复用,每个线程对应一个沙箱。省略 scope;旧值 "thread" 仍可接受,但会拒绝 "agent"。最多设置一个烘焙基础镜像:snapshot_name、snapshot_id 或 docker_image。对于私有 Docker 镜像,请添加 registry 并指定密码环境变量的名称;不要将密码写入源代码。
Agent 通过 ls、read_file、write_file、edit_file、delete、glob、grep 和 execute 工作。使用 instructions.md 说明它应在哪里工作,以及不得触碰哪些内容。mda delete 也会删除受管理的沙箱。
在 mda dev 期间,如果提供程序不可用,运行时会回退到本地临时目录并打印其路径。此回退仅用于开发——请在开发部署中验证沙箱行为。
计划任务
在 schedules/ 下每个文件定义一个计划任务,每个文件导出一个命名为 schedule 的计划任务。文件名即为计划任务名称。
# schedules/daily_digest.py
from managed_deepagents import define_schedule
schedule = define_schedule(
cron="0 8 * * 1-5",
timezone="America/Los_Angeles",
prompt="Summarize what you learned yesterday and list open questions.",
)
必须且只能定义 prompt(会转换为用户消息)或 input(结构化的 LangGraph 输入)之一。cron 必须是标准的五字段表达式;如果未指定 timezone,则 cron 按 UTC 运行。
计划任务默认使用临时线程——每次运行都会新建一个线程,并在之后删除。仅当运行需要累积持久化线程状态时,才传入 thread={"mode": "persistent", "id": "..."}。设置 deliver_to 可通过已配置的 Slack 频道发送结果。
声明会在编译时提取,不会运行你的代码:只能使用字面值和顶层字面量常量。不能使用环境变量、函数调用或 **kwargs。
mda deploy 会在部署上线后协调计划任务——它会删除 MDA 所有的 cron 任务,并根据当前文件重新创建,因此删除文件并重新部署即可移除对应的 cron。--no-wait 会完全跳过协调过程,因此添加、更改或移除计划任务时切勿使用它。
频道
频道将 Agent 连接到外部消息服务:入站事件会启动运行,响应则返回到同一对话中。**目前仅支持 Slack。**在 channels/ 下每个文件定义一个频道,每个文件导出一个命名为 channel 的频道。
# channels/slack.py
from managed_deepagents import channels
channel = channels.slack()
文件名决定频道名称及其入站路由——channels/slack.py 会在 POST /channels/slack/events 接收事件。名称必须唯一;文件名切勿使用 channels/channel.py。
由频道发起的运行会向工具和中间件公开 runtime.channel,其中包含规范化后的事件和对话地址,以及用于发送和更新消息的方法。普通 HTTP 运行和计划任务运行没有发起它们的频道,因此不会提供 runtime.channel。
Slack 设置需要项目根目录下的 slack-app-manifest.json,以及 .env 中的 SLACK_SIGNING_SECRET 和 SLACK_BOT_TOKEN。应将清单视为事实来源;在 .mda/ 下生成的文件属于构建产物,不得提交。runtime.channel 不会公开机器人令牌。
频道用于接收启动运行的消息。这不同于为 Agent 提供用于发起操作的 Slack 工具——项目可以选择其中一种,也可以两者都用。
频道线程归其来源对话所有,而凭据和存储访问权限仍限定于执行发送操作的调用方。从由首个主体拥有频道线程的版本升级时,现有 Slack 对话无法迁移;重新部署后,请开始新的对话或线程。
评测
MDA 评测是 Harbor 评测。evals/ 是规范的手动编写数据集;请将完整的 Harbor 任务直接放在 evals/<task>/ 下。.mda/evals/ 是生成内容,不得编辑或提交。
mda evals init -i
mda evals init 会初始化工作区并打印固定版本的 harbor run 交接命令;它不会运行试验。mda evals compile 现在是内部 Harbor 插件入口,因此不要告诉用户调用它。Harbor 的默认环境需要 Docker,且不会读取 .env——请在运行 Harbor 的 shell 中导出 LangSmith、模型和工具变量。如需更深入地了解评测设计,请参阅 [[eval-engineering]]。
CLI 参考
| 命令 | 用途 |
|---|---|
mda init <name> | 搭建项目脚手架。如果目标路径已存在,则失败。 |
mda build [path] | 编译为受管理的 LangGraph 应用,不进行部署。 |
mda dev [path] | 编译并在 LangSmith Studio 中运行本地开发服务器。 |
mda deploy [path] | 编译、同步 Context Hub、上传、部署并协调计划任务。 |
mda logs [path] | 实时查看已部署 Agent 的 Agent Server 日志。 |
mda delete [path] | 删除部署及其创建的 LangSmith 资源。别名:destroy。 |
mda connections create|list|get|delete|catalog | 管理工作区范围内的不透明密钥和 OAuth 注册信息。别名:connection。 |
mda channels init slack | 向当前项目添加 Slack 通道声明。别名:channel。 |
mda evals init | 初始化 Harbor 评测工作区并打印运行交接信息。别名:eval。 |
主要标志:
init:-i/--interactive、--model SPEC、--instructions TEXT、--instructions-file PATH、--memory agent|none、--no-sandbox、-c/--channel slackbuild:--out OUT(默认为<path>/.mda/build;仅接受不存在、为空或先前由 MDA 创建的构建目录)dev:--port、--hostname、--no-browser、--no-reload、--tunneldeploy:--name、--deployment-type dev|prod、--workspace-id、--no-wait、--context-strategy、--wait-timeout-secondsconnections:--project PATH,以及各子命令专用的密钥和 OAuth 标志logs:--name、--lines、--level、--follow/--no-follow、--workspace-iddelete:--name、--workspace-id、--yes
安装的软件包决定所用语言:PyPI 上的 mda 会搭建 Python 项目脚手架,npm 上的 mda 会搭建 TypeScript 项目脚手架。它不会根据当前目录推断语言。Python 项目的 mda dev 需要 uv,并会自行解析 LangGraph 开发服务器。
mda delete具有破坏性,会删除部署及其 LangSmith 资源。运行前请先向用户确认,且绝不要在未获提示时传入--yes——该标志会跳过本应进行的确认。
部署和 Context Hub
身份验证使用项目 .env 或 shell 中的 LANGSMITH_API_KEY。在未找到密钥的交互式终端中,mda deploy 可以提示输入密钥或使用浏览器登录;浏览器登录会在本机缓存短期个人令牌,而不是将其写入 .env。如果密钥需要选择工作区,请使用 --workspace-id 或 LANGSMITH_WORKSPACE_ID。
mda deploy 会将本地输入路由到不同的托管平台:
instructions.md + skills/** -> Context Hub deploy-owned context
.env -> deploy auth + non-reserved hosted secrets (never archived)
project source -> .mda/build archive -> hosted deployment
schedules/** -> LangSmith cron jobs, after the deployment is live
非保留的 .env 条目——提供商密钥、工具凭据、数据库 URL——会作为托管部署密钥转发。诸如 LANGSMITH_API_KEY 之类的保留平台变量用于验证身份或配置部署,不会作为用户管理的密钥上传。对于部署密钥,mda deploy 会刻意不从进程环境复制值:请将提供商或工具密钥放入项目 .env,或将其配置为 LangSmith 工作区密钥。shell 仍适用于本地 mda dev。
Context Hub 包含 /instructions.md 和 /skills/**(由部署管理,每次部署时重新同步),以及 /memories/agent/**(由运行时管理,部署后保留)。
从 GitHub 部署
LangSmith 可以从已连接的 GitHub 仓库部署 MDA 项目。选择仓库、分支或标签,以及包含 agent.py 或 agent.ts 的仓库相对项目目录;langgraph.json 会自动生成,不应提交。平台会运行隐藏的 mda prepare 构建步骤,以编译项目、将指令和技能同步到 Context Hub、打包 sandbox/setup.sh,并协调计划任务和频道。当修订应自动重新构建时,请启用推送时构建。
对于从 GitHub 来源的部署,仓库是部署管理的 Context Hub 内容的权威来源。请在 Git 中编辑 instructions.md 和 skills/**,并重新构建,不要将 Hub 副本视为可独立编辑的内容。请通过部署密钥或密钥引用提供运行时凭据;构建不会读取仓库的 .env。预览构建会编译并打包,但不会协调计划任务或频道。
mda prepare 是平台内部命令,在 CLI 帮助中隐藏。切勿要求用户手动运行。
故障排除:no agent entry file found → 在根目录添加 agent.py。401/403 → 密钥所属工作区没有 beta 访问权限。Context Hub 冲突 → 重新运行部署。构建超过 200 MB → 删除生成的构件。BUILD_FAILED / DEPLOY_FAILED → 打开打印出的 URL 并查看修订日志。
人机协同
使用 interrupt_on 在敏感工具调用前暂停,并使用 permissions 限制文件系统路径:
agent = define_deep_agent(
name="support-agent",
model="anthropic:claude-sonnet-4-6",
tools=[refund_customer],
interrupt_on={"refund_customer": True},
)
interrupt_on 的行为与 LangChain 的人机协同中间件相同;批准/编辑/拒绝语义请参阅 [[langgraph-human-in-the-loop]]。中断需要持久化的线程状态,而托管运行时负责管理检查点,因此无需额外设置。
在运行 mda dev 时,可在 Studio 中响应中断。对于已部署的 Agent,请通过 Agent Server/LangGraph API 使用 Command(resume=...) 负载恢复;mda deploy 会打印 Agent Server URL。
注意事项
- 在
define_deep_agent/defineDeepAgent中,必须设置name=。缺少该字段的定义会失败。 - 模型 ID 必须带提供商前缀:使用
anthropic:claude-sonnet-4-6,而不是不带前缀的模型名称。Python 使用google_genai:,TypeScript 使用google-genai:,Gateway 使用provider/model。 - 不要在 Agent 定义中设置托管字段(
backend、store、checkpointer、memory、skills、系统提示词)。 - 通过
memory.py显式启用内存,而不是将其作为构造函数参数。disable_memory是旧版用法——请声明或删除memory.py。 - MCP 声明位于
tools/mcp.*。 请从defineMcp({ servers: ... })/define_mcp(servers=...)导出mcp。connectors.mcp、connectors/mcp.*和mcpServers是已弃用的 0.7.x 兼容接口,不适用于新代码。 - 连接的作用范围是工作区。 连接标识名并非某个 Agent 独有,
mda connections list列出的是整个工作区的连接,而不仅是当前部署的连接。 - 添加托管文件后,请重启
mda dev。 新增的memory.py、identity.py、tools/mcp.py、schedules/或channels/声明会在编译时发现,而非通过热重载发现。 --no-wait会跳过计划任务协调,并在状态变为DEPLOYED前退出。- 计划任务声明必须是静态字面量——编译器会在不运行代码的情况下提取这些声明。
.env永远不会被打包归档,且.gitignore必须将其排除在版本控制之外。不要代替用户将有效密钥写入其中。仅在 Shell 中设置的提供商密钥可用于本地开发,但不会保留到部署中。- 已安装的软件包决定使用 Python 还是 TypeScript。 不要声称
mda init会根据附近的清单推断语言。 --gateway已被移除。 请显式配置由 Gateway 提供支持的模型,不要使用之前的脚手架标志。- SDK 更新很快。 请通过已安装的
mda --help验证标志,并根据已安装的软件包确认开发接口。请使用define_sandbox(...),而不是sandboxes.langsmith(...);默认会生成identity.py;mda prepare和mda evals compile是内部入口点。