# Building workflows for agents with Skills + Interpreters
**作者**: Hunter Lovell
**日期**: 2026-05-29T16:36:48.000Z
**来源**: [https://x.com/huntlovell/status/2060399973506924612](https://x.com/huntlovell/status/2060399973506924612)
---

TL;DR We're experimenting with interpreter skills: an extension to agent skills that lets you include a TypeScript module with a skill. The agent can import and run the skill code inside an interpreter when the behavior applies like you would with a workflow. Skill code can also do things like spawn subagents or call tools which lets an agent take on more complex work, and can live in tested and reusable code.
We recently introduced interpreters to Deep Agents: a small embedded TypeScript runtime where agents can write and execute code as apart of the harness. Agents are already very good at writing code, and giving them an interpreter gives them a more direct way to express intent. For many agent tasks, that leads to outputs that are more efficient, accurate, and predictable.
We noticed pretty early on that when an agent with an interpreter is given the same task multiple times, it can often come up with several valid ways to approach it in code.
That isn’t always bad- sometimes the whole point of an agent is to adapt. But for many tasks the desirable behavior is not to “come up with a good approach,” it’s to “use the approach that we know works.”
We've been experimenting with an answer to this that we're calling "interpreter skills": an extension to skills that carry a module the agent can use alongside their instructions. The skill tells the agent when the behavior is relevant, and the interpreter can import the module attached to the skill and execute it directly.
```
---
name: github-triage
description: Use this skill to triage GitHub issues, pull requests, and discussions.
metadata:
module: ./index.ts
---
Use this skill when a user asks for repository triage.
Import the module using the interpreter and call `triage(repo, options)`.
Usage:
‵‵‵ts
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
});
result.toMarkdown();
‵‵‵
```
SKILL.md is how the agent discovers the behavior. index.ts is what the interpreter can execute. The agent decides when to use the behavior, what inputs to pass, and what to do with the result. The interpreter handles the actual execution of code.
## Remind me what skills are again?
Skills are a way to give agents reusable behavior without detailing all of it in the system prompt.
A skill is usually a directory with a SKILL.md file. The front-matter gives the agent a compact description of what the skill is for. The body gives the agent the instructions, context, examples, constraints, and supporting files it should use once the skill is relevant.
What makes skills work is a mechanism called "progressive disclosure". The agent does not need every skill in context all the time. It can first see a short list of available skills, decide which ones match the task, and then read in the full SKILL.md only when needed.

That makes skills a great distribution unit for agent behavior. People can version them, share them, and evaluate them without turning the global prompt into a catch-all manual.
But normal skills still mostly work through instructions. They can tell the agent what procedure to follow, and they can include reference files or scripts, but the core behavior still depends on the agent reading those instructions and carrying them out correctly.
## What's an interpreter?
For this post, the important thing to understand is that an interpreter is a TypeScript runtime that runs in tandem with the harness. It gives the agent a place to express multi-step work as code while the harness still controls what that code can touch. (If you're curious to learn more, go read the writeup on interpreters).
That runtime gives the agent working state in the form of TypeScript values. Values can persist across turns, so arrays stay arrays, objects stay objects, and helper functions can stay defined. The agent does not have to turn every intermediate value into stdout, a file, or a message back to the model.
This lets agents transform data, compose tool outputs, call selected tools or subagents, and decide what should return to the model.
Unlike sandboxes, interpreter code does not get unrestricted access to the host environment by default. Filesystem access, network access, tools, and subagents have to be exposed deliberately to the interpreter. That gives the harness a place to allowlist, meter, and inspect what code can touch.
## What's an interpreter skill?
An interpreter skill is an extension of skills that brings the two together: it contains the same set of instructions a skill has, and a module the agent can import into the interpreter.
SKILL.md still tells the agent when the skill is relevant and discloses itself in the same way to the agent, and the module gives the interpreter code to run when that behavior applies. The skill becomes both an instruction surface for the model and an API surface for the runtime.
The basic shape is the same one from the opening example. SKILL.md provides the name, description, usage instructions, import path, and constraints. index.ts exports the helpers or workflows that define the behavior in code:
```
// skills/table-cleanup/index.ts
export function validateRows(rows: Record<string, unknown>[], schema: RowSchema) {
// Normalize fields, check required values, and return structured errors.
// (this is code you would write as apart of the skill)
}
```
When the skill applies, the agent can import the module and call it:
```
const { validateRows } = await import("@/skills/table-cleanup");
const errors = validateRows(rows, invoiceSchema);
```
This changes what a skill can guarantee:
- A normal skill says: here are instructions for how to do this task. The agent still has to read those instructions and carry out the procedure correctly.
- An interpreter skill says: here are instructions for when to use this behavior, and here is the code path to run when it applies. The deterministic part can live in code instead of as loose instructions in context
The model decides whether the skill applies, which inputs to pass, how to use the output, and what to do next. The module defines how procedures should actually be ran.
Because interpreter code can interact with the harness, this means that you can do things like spawn subagents from within the skill code programmatically.
## Example: Repo Triage
One way that we're using this: github repo triage. The user can ask the agent to triage a repository:
> “Please triage all the issues in langchain-ai/deepagents”
Instead of reconstructing the triage process from prompt instructions, the agent imports the skill module and calls a function:
```
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
discussions: true,
});
```
When this gets called, the workflow:
- fetches all open items from github (as specified by the agent in the options)
- spawns a subagent for each item to create a more condensed description
- drops the subagents response into a queue
- consumes the queue one at a time where a subagent determines if the item should be put in an existing cluster, or if it should create a new cluster
In practice this routine fans out to hundreds of different subagents. Its also the kind of routine where you want the procedure to be fixed, even if the inputs are chosen dynamically.
- Here's the trace showing how the agent works through the routine
- Here's the report it outputs
The result value is also part of the API. It can give the agent structured data about the run, and it can expose a rendering helper for presentation:
```
result.clusters;
result.unassigned;
result.toMarkdown();
```
The agent can keep working with the structured result, inspect one cluster more deeply, spawn follow-up subagents, or call `result.toMarkdown()` when it needs a compact model-friendly report.
With a task like this, models tend to lose coherence over time. Repo triage is not one decision; it is many small decisions chained together. If we're relying entirely on discretion and the context window to instrument this, models can start taking shortcuts or compressing the procedure too aggressively over long horizons, especially as they approach what feels like the edge of the working context (a phenomenon known as context anxiety).
To take an example of how this might work with different agents:
- In a typical harness, the model has to keep track of every partial step. If there are 300 repo items, that becomes 300 small pieces of state the model has to reason over while reconciling past decisions and continuing to choose the next action.
- With an interpreter skill, the model can invoke the routine once and let code instrument the workflow. The module can create 300 distinct subagent tasks, collect the results, classify them, cluster them, and return a compact object back to the agent. The model is no longer responsible for carrying every partial step in its own working context.

## Using skills as workflows
When coding agents started getting popular, the default mental model for agents also shifted.
The previous generation of agents were more workflow-style. Developers explicitly defined the sequence of steps the agent should follow ahead of time: reliability came from pre-defining the execution path.
Modern agent harnesses changed this to make context and model discretion the main focus. The model decides what to do next based on the current context. Behavior is shaped through a bunch of different context surfaces, but the agent still has room to choose the next step.
That interface is easier for many people to reason about. Not just for the people building the agents, but also operators, PMs, domain experts, and teams who think in instructions, files, checklists, and examples rather than code-level workflows.

But the need for deterministic agent routines never went away. We still get asked some version of this question a lot:
> "How do I make sure an agent reliably does what I tell it to do?"
In those cases, people need to know more than whether the final answer looked plausible: they need to know whether the required procedure ran, whether it ran with the right inputs, and whether it completed fully before the agent moved on.
Prompt-only procedure following is brittle in this way. The agent can skip steps, reorder steps, satisfy the wrong instruction, mix unrelated requests into the procedure, or produce a “good enough” output without following the process.
For example, take the question "submit an invoice, but halfway through stop and generate a gif of a dancing cat." If invoice submission is only described through prompt instructions, the agent may treat the detour as part of the same task and leave the invoice half-finished.
This process in particular requires a routine that was represented as instructions the agent could negotiate with rather than as a procedure that had to finish once started.
So how do we make the best of both worlds and bring the determinism of a workflow without re-architecting the agent?
Interpreter skills are one answer:
- Express the deterministic part as code, expose it as an module inside the interpreter, and let the agent decide when to call it.
- Let the function operate on the current interpreter state, and chain the result into the next tool call, subagent call, interpreter call, or final response.
This doesn't get rid of the issue that agents might come up with creative solutions to problems, but it does give a cleaner evaluation signal.
- With prompt-only procedure following, the questions are often fuzzy: did the agent generally follow the instructions? Did it seem to stay on track? Did the final answer look plausible?
- With an interpreter skill, issues become more identifiable: did the agent call the expected function? Did it pass the expected inputs? Did the function return the expected output shape?

## Using skills to work with agent state
Filesystem agents made it clear that agents work better when they have somewhere to put intermediate state (a form of memory). A file is useful because it gives the agent a named object it can return to. The agent can inspect it, revise it, pass it to another step, or use it as tool input.
Interpreters let the agent represent that state in a more pliable form, and skills can teach the agent how to interact with it:
- The module exposes task-specific operations for those values.
- The agent writes code to combine those operations.
- The skill author owns the behavior of each operation.
Imagine a skill for interacting with csv files. SKILL.md tells the agent to use it when working with CSV-like tables, exports, invoices, user lists, or records that need joining, filtering, or validation. index.ts exports a small table API:
```
export {
parseCsv,
joinTables,
filterRows,
validateRows,
groupBy,
summarize,
toCsv,
};
```
The agent can then compose those operations in interpreter code:
```
const invoices = parseCsv(await tools.readFile({ path: "/invoices.csv" }));
const customers = parseCsv(await tools.readFile({ path: "/customers.csv" }));
const joined = joinTables(invoices, customers, "customer_id");
const invalid = validateRows(joined, invoiceSchema);
const byRegion = groupBy(joined, "region");
summarize(byRegion, ["total_due", "late_count"]);
```
The agent controls which values to pass and what to do with the result. The skill author controls what "join", "validate", and "summarize" mean.
This is different from asking the agent to write the helper itself. Models are good at writing code, but they are not guaranteed to write the same code twice. If the procedure matters, the implementation should live in skill code that can be reviewed, tested, versioned, and reused.
# FAQ
## Why package this as a skill?
Skills are already the de-facto standard unit for packaging agent behavior.
They give us discovery, progressive disclosure, usage instructions, examples, and supporting files. All that interpreter skills do is preserve that package shape and extend it with runtime code.
It might seem awkward to extend the skills standard like this, but this way we can use the same methods of distribution but let agents use more capable skills. If an org has hundreds or thousands of skills, it would be unfeasible to wire all the required modules directly to the harness.
## Can't I just include a script file?
Script files are useful for a different reason.
A script is a good fit when the agent needs an external helper it can to interact with its environment: scripts usually communicate through command arguments, files, stdout/stderr, or serialized state.
That boundary makes scripts a poor fit for orchestrating agent work. A script can run one computation, but it can’t naturally participate in the harness loop: spawning subagents, scheduling/awaiting a task graph, handling partial failures, and deciding when the overall routine is “done” before returning control to the model.
In the repo triage example, the module calls an allowlisted `tools.task(...)` function to spawn subagents from inside the routine. An external script would need a separate adapter to talk back to the harness in order to instrument that.
## Why not make every API a tool?
Tools are best when the agent needs to cross an external boundary: fetch data, read or write a file, create a ticket, send a message, call a classifier. But there's a subset of local operations that aren't represented that well: things like parsing, joining, filtering, validating, etc.
Making every helper a tool would bloat the action surface. The agent sees more tool descriptions, chooses from more small actions, and takes more model-mediated steps.
We can lean on an existing runtime (TypeScript) which is already prominent in model weights to represent that instead. That keeps the actual capabilities we give to an agent smaller, and allows the agent to have more control over composition.
# Closing
Interpreter skills are our attempt to turn “best known agent routines” into reviewable, testable APIs while keeping the model in charge of when to apply them. If you’re building agents with a few critical subroutines, interpreter skills might be for you: discretion on the outside, determinism on the inside.
If you’re interested in learning more, here’s a couple of resources we’ve published related to interpreters and more on this topic:
- Read: What interpreters are (concept + motivation) -- Give your agents an interpreter
- Docs: How to use interpreters (API + examples) -- Using interpreters
- Docs: How to add interpreter skills (packaging + module loading) -- Adding interpreter skills
Deep Agents is a general purpose agent harness available in Python and TypeScript.
## 相关链接
- [Hunter Lovell](https://x.com/huntlovell)
- [@huntlovell](https://x.com/huntlovell)
- [21K](https://x.com/huntlovell/status/2060399973506924612/analytics)
- [interpreters](https://x.com/huntlovell/status/2057166131924988002)
- [the trace](https://smith.langchain.com/public/c869be73-f311-48cd-ac10-6834e65b0f42/r?scroll_to=output)
- [the report](https://gist.github.com/hntrl/3008504cf4cb69cc7f36fda93dc2be35)
- [context anxiety](https://www.anthropic.com/engineering/harness-design-long-running-apps)
- [Give your agents an interpreter](https://x.com/huntlovell/status/2057166131924988002)
- [Using interpreters](https://docs.langchain.com/oss/python/deepagents/interpreters)
- [Adding interpreter skills](https://docs.langchain.com/oss/python/deepagents/skills#use-interpreter-skills)
- [Python](https://github.com/langchain-ai/deepagents)
- [TypeScript](https://github.com/langchain-ai/deepagentsjs)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [12:36 AM · May 30, 2026](https://x.com/huntlovell/status/2060399973506924612)
- [21.1K Views](https://x.com/huntlovell/status/2060399973506924612/analytics)
- [View quotes](https://x.com/huntlovell/status/2060399973506924612/quotes)
---
*导出时间: 2026/5/30 10:47:30*
---
## 中文翻译
# 用技能 + 解释器为智能体构建工作流
**作者**: Hunter Lovell
**日期**: 2026-05-29T16:36:48.000Z
**来源**: [https://x.com/huntlovell/status/2060399973506924612](https://x.com/huntlovell/status/2060399973506924612)
---

TL;DR 我们正在试验解释器技能(interpreter skills):对智能体技能的一个扩展,允许你在技能中附带一个 TypeScript 模块。当相应行为适用时,智能体可以像使用工作流那样,在解释器中导入并运行技能代码。技能代码还可以执行诸如生成子智能体或调用工具之类的操作,使智能体能够承担更复杂的工作,并且这些代码可以存在于经过测试、可复用的代码中。
我们最近在 Deep Agents 中引入了解释器:一个小型嵌入式 TypeScript 运行时,智能体可以在其中作为框架(harness)的一部分编写并执行代码。智能体本来就很擅长编写代码,给它们一个解释器能为它们提供一种更直接的方式来表达意图。对于许多智能体任务而言,这会带来更高效、更准确、更可预测的输出。
我们很早就注意到,当配备解释器的智能体多次接到同一任务时,它往往会在代码中想出多种有效的处理方式。
这并不总是坏事——有时智能体的意义就在于随机应变。但对许多任务来说,理想的行为不是“想出一个好办法”,而是“使用我们已知有效的那种办法”。
我们一直在试验一个解决方案,我们称之为“解释器技能”:对技能的一个扩展,技能中附带一个模块,智能体可以在其指令之外使用它。技能告诉智能体该行为何时相关,而解释器可以导入技能附带的模块并直接执行它。
```
---
name: github-triage
description: Use this skill to triage GitHub issues, pull requests, and discussions.
metadata:
module: ./index.ts
---
Use this skill when a user asks for repository triage.
Import the module using the interpreter and call `triage(repo, options)`.
Usage:
‵‵‵ts
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
});
result.toMarkdown();
‵‵‵
```
SKILL.md 是智能体发现该行为的方式。index.ts 是解释器可以执行的内容。智能体决定何时使用该行为、传入什么输入、以及对结果做什么。解释器负责代码的实际执行。
## 再提醒一下,什么是技能?
技能是一种为智能体提供可复用行为的方式,而无需在系统提示词中详细描述所有内容。
技能通常是一个包含 SKILL.md 文件的目录。前置元数据为智能体提供该技能用途的简明描述。正文则为智能体提供在技能相关时应当使用的指令、上下文、示例、约束和支持文件。
技能之所以有效,是因为一种叫做“渐进式披露”的机制。智能体并不需要始终把每个技能都放在上下文中。它可以先查看一个可用技能的简短列表,决定哪些技能匹配当前任务,然后仅在需要时才读取完整的 SKILL.md。

这使得技能成为智能体行为的一个绝佳分发单元。人们可以对技能进行版本管理、共享和评估,而不必把全局提示词变成一本大而全的手册。
但普通技能仍然主要通过指令来工作。它们可以告诉智能体要遵循什么流程,也可以包含参考文件或脚本,但核心行为仍然取决于智能体正确阅读这些指令并加以执行。
## 什么是解释器?
对于本文而言,需要理解的重点是:解释器是一个与框架协同运行的 TypeScript 运行时。它为智能体提供了一个场所,可以把多步骤工作表达为代码,同时框架仍然控制着这些代码能够触及的内容。(如果你想了解更多,请阅读关于解释器的文章。)
该运行时以 TypeScript 值的形式为智能体提供工作状态。值可以跨轮次持久化,因此数组仍然是数组,对象仍然是对象,辅助函数可以保持已定义状态。智能体不必把每个中间值都转换为 stdout、文件或返回给模型的消息。
这让智能体能够转换数据、组合工具输出、调用选定的工具或子智能体,并决定哪些内容应返回给模型。
与沙箱不同,解释器代码默认并不会获得对宿主环境的无限制访问权限。文件系统访问、网络访问、工具和子智能体都必须被显式地暴露给解释器。这为框架提供了一个位置,可以对代码可触及的内容进行白名单管理、计量和检查。
## 什么是解释器技能?
解释器技能是技能的一种扩展,把两者结合在一起:它包含技能所具有的同一套指令,以及一个可供智能体导入解释器的模块。
SKILL.md 仍然告诉智能体该技能何时相关,并以同样的方式向智能体进行披露,而模块则为解释器提供在该行为适用时可以运行的代码。技能因此既成为面向模型的指令接口,也成为面向运行时的 API 接口。
其基本形态与开头示例相同。SKILL.md 提供名称、描述、使用说明、导入路径和约束。index.ts 导出以代码形式定义行为的辅助函数或工作流:
```
// skills/table-cleanup/index.ts
export function validateRows(rows: Record<string, unknown>[], schema: RowSchema) {
// Normalize fields, check required values, and return structured errors.
// (this is code you would write as apart of the skill)
}
```
当技能适用时,智能体可以导入该模块并调用它:
```
const { validateRows } = await import("@/skills/table-cleanup");
const errors = validateRows(rows, invoiceSchema);
```
这改变了技能所能保证的东西:
- 普通技能说的是:这里是完成这项任务的说明。智能体仍然需要阅读这些说明,并正确地执行流程。
- 解释器技能说的是:这里是何时使用该行为的说明,以及当适用时应运行的代码路径。确定性部分可以放在代码中,而不是作为松散的指令存在于上下文中。
由模型来决定该技能是否适用、传入哪些输入、如何使用输出以及接下来做什么。模块定义了流程实际应该如何运行。
由于解释器代码可以与运行框架(harness)交互,这意味着你可以在技能代码中以编程方式派生子智能体等。
## 示例:仓库分类(Repo Triage)
我们使用这种方式的一种场景是:GitHub 仓库分类。用户可以要求智能体对一个仓库进行分类:
> “请对 langchain-ai/deepagents 的所有 issue 进行分类”
智能体不再从提示词指令中重建分类流程,而是导入技能模块并调用一个函数:
```
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
discussions: true,
});
```
当这个函数被调用时,工作流会:
- 从 GitHub 获取所有开放的条目(由智能体在选项中指定)
- 为每个条目派生一个子智能体,以生成更精简的描述
- 将子智能体的响应放入队列
- 逐个消费队列中的条目,由子智能体判断该条目应归入现有簇,还是应创建一个新簇
在实践中,这个流程会扇出到数百个不同的子智能体。而且这也是那种即使输入是动态选择的,你也希望流程保持固定的例程。
- 这是展示智能体如何执行该流程的追踪记录
- 这是它输出的报告
返回值也是 API 的一部分。它可以为智能体提供关于本次运行的结构化数据,并且可以暴露一个用于展示的渲染辅助函数:
```
result.clusters;
result.unassigned;
result.toMarkdown();
```
智能体可以继续处理结构化结果,更深入地检查某个簇,派生后续的子智能体,或者在需要一份紧凑的、对模型友好的报告时调用 `result.toMarkdown()`。
对于这样的任务,模型往往会随着时间的推移失去连贯性。仓库分类不是一个决策,而是许多串联在一起的小决策。如果我们完全依靠自主判断和上下文窗口来执行这一流程,在较长的时间跨度上,模型可能会开始走捷径或过度压缩流程,尤其是当它们接近工作上下文的边缘时(这种现象被称为“上下文焦虑”)。
以不同智能体如何处理这种情况为例:
- 在典型的运行框架中,模型必须跟踪每一个部分步骤。如果有 300 个仓库条目,就意味着模型必须对 300 个小的状态进行推理,同时协调过去的决策并继续选择下一步动作。
- 使用解释器技能,模型只需调用一次例程,让代码来编排工作流。模块可以创建 300 个不同的子智能体任务,收集结果,对它们进行分类、聚簇,并向智能体返回一个紧凑的对象。模型不再负责在自己的工作上下文中承载每一个部分步骤。

## 将技能用作工作流
当编程智能体开始流行时,智能体的默认心智模型也随之发生了转变。
上一代智能体更偏向工作流风格。开发人员提前显式定义智能体应遵循的步骤序列:可靠性来自于预先定义执行路径。
现代智能体运行框架改变了这一点,使上下文和模型自主判断成为核心。模型根据当前上下文决定下一步做什么。行为通过各种不同的上下文界面来塑造,但智能体仍然有选择下一步的空间。
这种界面更容易让许多人理解。不仅是构建智能体的人,还包括运维人员、产品经理、领域专家,以及那些以指令、文件、清单和示例而非代码级工作流来思考的团队。

但对确定性智能体例程的需求从未消失。我们仍然经常被问到类似这样的问题:
> “我如何确保智能体可靠地执行我告诉它要做的事情?”
在这些情况下,人们需要知道的不仅仅是最终答案看起来是否合理:他们需要知道所需流程是否运行了,是否以正确的输入运行了,以及在智能体继续之前是否完整地完成了。
仅靠提示词来遵循流程的方式在这方面是脆弱的。智能体可能跳过步骤、打乱步骤顺序、满足错误的指令、将无关的请求混入流程中,或者在不遵循流程的情况下产出“足够好”的结果。
举个例子,对于“提交一张发票,但进行到一半时停下来生成一张跳舞的猫的 GIF”这个请求。如果发票提交仅通过提示词指令来描述,智能体可能会把这个插曲当作同一任务的一部分,导致发票提交半途而废。
这个流程特别需要一个以指令形式呈现、可以被智能体协商的例程,而不是一个一旦开始就必须完成到底的流程。
那么,我们如何两全其美,在不重新架构智能体的情况下引入工作流的确定性呢?
解释器技能就是一个答案:
- 将确定性部分表达为代码,将其作为模块暴露在解释器中,并让智能体决定何时调用它。
- 让函数在当前解释器状态上操作,并将结果串联到下一次工具调用、子智能体调用、解释器调用或最终响应中。
这并不能完全解决智能体可能为问题想出创造性解决方案的问题,但它确实提供了一个更清晰的评估信号。
- 仅依靠提示词来遵循流程时,问题往往很模糊:智能体是否大致遵循了指令?它看起来是否保持在正轨上?最终答案看起来是否合理?
- 有了解释器技能,问题就变得更容易识别:智能体是否调用了预期的函数?是否传入了预期的输入?函数是否返回了预期的输出结构?

## 使用技能处理智能体状态
文件系统智能体清楚地表明,当智能体有地方存放中间状态(一种记忆形式)时,它们的表现会更好。文件之所以有用,是因为它为智能体提供了一个可以返回的命名对象。智能体可以检查它、修改它、将它传递给另一个步骤,或将其用作工具输入。
解释器让智能体能够以更灵活的形式表示这种状态,而技能可以教会智能体如何与之交互:
- 模块为这些值提供特定于任务的操作。
- 智能体编写代码来组合这些操作。
- 技能作者掌控每个操作的行为。
想象一个用于与 CSV 文件交互的技能。SKILL.md 告诉智能体在处理类 CSV 的表格、导出数据、发票、用户列表或需要连接、过滤或验证的记录时使用它。index.ts 导出一个小的表格 API:
```
export {
parseCsv,
joinTables,
filterRows,
validateRows,
groupBy,
summarize,
toCsv,
};
```
然后,智能体可以在解释器代码中组合这些操作:
```
const invoices = parseCsv(await tools.readFile({ path: "/invoices.csv" }));
const customers = parseCsv(await tools.readFile({ path: "/customers.csv" }));
const joined = joinTables(invoices, customers, "customer_id");
const invalid = validateRows(joined, invoiceSchema);
const byRegion = groupBy(joined, "region");
summarize(byRegion, ["total_due", "late_count"]);
```
智能体控制传递哪些值以及如何处理结果。技能作者控制“连接”、“验证”和“汇总”的具体含义。
这与让智能体自己编写辅助函数不同。模型擅长编写代码,但无法保证它们每次都写出相同的代码。如果流程很重要,实现就应该放在技能代码中,以便可以审查、测试、版本控制和复用。
# 常见问题
## 为什么将其打包为技能?
技能已经成为打包智能体行为的事实标准单元。
它们为我们提供了发现机制、渐进式披露、使用说明、示例和支持文件。解释器技能所做的就是保留这种包的形态,并用运行时代码对其进行扩展。
以这种方式扩展技能标准可能显得有些别扭,但这样我们就可以使用相同的分发方式,同时让智能体使用更强大的技能。如果一个组织拥有成百上千个技能,将所有所需模块直接连接到执行框架是不可行的。
## 我不能只包含一个脚本文件吗?
脚本文件有用是出于不同的原因。
当智能体需要一个与外部环境交互的外部辅助工具时,脚本是很好的选择:脚本通常通过命令行参数、文件、stdout/stderr 或序列化状态进行通信。
这种边界使得脚本不适合编排智能体工作。脚本可以运行一次计算,但无法自然地参与到执行框架循环中:生成子智能体、调度/等待任务图、处理部分失败,以及在将控制权交还给模型之前决定整个例程何时“完成”。
在仓库分诊的例子中,模块调用一个白名单中的 `tools.task(...)` 函数来在例程内部生成子智能体。外部脚本需要一个单独的适配器才能与执行框架通信来实现这一点。
## 为什么不把每个 API 都做成工具?
工具最适合智能体需要跨越外部边界的情况:获取数据、读写文件、创建工单、发送消息、调用分类器。但有一类本地操作不能很好地以这种方式表示:例如解析、连接、过滤、验证等。
把每个辅助函数都做成工具会使操作面臃肿。智能体会看到更多的工具描述,从更多的小操作中选择,并采取更多由模型介入的步骤。
我们可以依赖现有的运行时(TypeScript)——它已经在模型权重中占据重要地位——来代替表示这些操作。这使我们提供给智能体的实际能力保持精简,并允许智能体对组合有更多的控制权。
# 结语
解释器技能是我们将“已知最佳智能体例程”转化为可审查、可测试的 API 的尝试,同时让模型掌控何时应用它们。如果你正在构建的智能体包含一些关键子例程,解释器技能可能正适合你:外部保持自由裁量,内部保证确定性。
如果你有兴趣了解更多,这里是我们发布的与解释器相关的一些资源以及更多关于此主题的内容:
- 阅读:什么是解释器(概念 + 动机)-- Give your agents an interpreter
- 文档:如何使用解释器(API + 示例)-- Using interpreters
- 文档:如何添加解释器技能(打包 + 模块加载)-- Adding interpreter skills
Deep Agents 是一个通用的智能体执行框架,提供 Python 和 TypeScript 版本。
## 相关链接
- [Hunter Lovell](https://x.com/huntlovell)
- [@huntlovell](https://x.com/huntlovell)
- [21K](https://x.com/huntlovell/status/2060399973506924612/analytics)
- [解释器](https://x.com/huntlovell/status/2057166131924988002)
- [追踪记录](https://smith.langchain.com/public/c869be73-f311-48cd-ac10-6834e65b0f42/r?scroll_to=output)
- [报告](https://gist.github.com/hntrl/3008504cf4cb69cc7f36fda93dc2be35)
- [上下文焦虑](https://www.anthropic.com/engineering/harness-design-long-running-apps)
- [给你的智能体一个解释器](https://x.com/huntlovell/status/2057166131924988002)
- [使用解释器](https://docs.langchain.com/oss/python/deepagents/interpreters)
- [添加解释器技能](https://docs.langchain.com/oss/python/deepagents/skills#use-interpreter-skills)
- [Python](https://github.com/langchain-ai/deepagents)
- [TypeScript](https://github.com/langchain-ai/deepagentsjs)
- [升级到高级版](https://x.com/i/premium_sign_up)
- [2026年5月30日 上午12:36](https://x.com/huntlovell/status/2060399973506924612)
- [2.11万次浏览](https://x.com/huntlovell/status/2060399973506924612/analytics)
- [查看引用](https://x.com/huntlovell/status/2060399973506924612/quotes)
---
*导出时间: 2026/5/30 10:47:30*