# 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*
---
## 中文翻译
# 使用 Skills + Interpreters 为 Agent 构建工作流
**作者**: Hunter Lovell
**日期**: 2026-05-29T16:36:48.000Z
**来源**: [https://x.com/huntlovell/status/2060399973506924612](https://x.com/huntlovell/status/2060399973506924612)
---

TL;DR 我们正在实验解释器技能:这是 Agent 技能的一个扩展,允许你将一个 TypeScript 模块包含在技能中。Agent 可以在适用该行为时,像使用工作流一样,在解释器内导入并运行技能代码。技能代码还可以执行生成子 Agent 或调用工具等操作,这使得 Agent 能够承担更复杂的工作,并且这些代码可以位于经过测试和可复用的代码库中。
我们最近为 Deep Agents 引入了解释器:这是一个小型的嵌入式 TypeScript 运行时,Agent 可以在其中编写和执行代码作为系统的一部分。Agent 已经非常擅长编写代码,而赋予它们解释器则提供了一种更直接的表达意图的方式。对于许多 Agent 任务来说,这带来了更高效、更准确且更可预测的输出结果。
我们很早就注意到,当拥有解释器的 Agent 多次执行同一任务时,它经常能想出多种有效的代码实现方法。
这并不总是坏事——有时 Agent 的全部意义就在于适应能力。但对于许多任务而言,理想的行为不是“想出一个好方法”,而是“使用我们知道行之有效的方法”。
我们一直在为此实验一种解决方案,我们称之为“解释器技能”:这是技能的扩展,它携带一个 Agent 可以与其指令一起使用的模块。该技能告诉 Agent 何时该行为是相关的,而解释器可以导入附加到该技能的模块并直接执行它。
```
---
name: github-triage
description: 使用此技能对 GitHub issues、pull requests 和 discussions 进行分类。
metadata:
module: ./index.ts
---
当用户请求对代码仓库进行分类时使用此技能。
使用解释器导入模块并调用 `triage(repo, options)`。
用法:
‵‵‵ts
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
});
result.toMarkdown();
‵‵‵
```
SKILL.md 是 Agent 发现行为的方式。index.ts 是解释器可以执行的内容。Agent 决定何时使用该行为、传递什么输入以及如何处理结果。解释器负责代码的实际执行。
## 再提醒我一下,什么是技能?
技能是一种赋予 Agent 可复用行为而无需在系统提示词中详尽说明所有细节的方式。
技能通常是一个包含 SKILL.md 文件的目录。Front-matter 为技能提供了用途的简明描述。正文提供了 Agent 在该技能相关时应使用的指令、上下文、示例、约束和支持文件。
技能之所以有效,是因为一种称为“渐进式披露”的机制。Agent 不需要时刻掌握上下文中的每一个技能。它首先可以看到可用技能的简短列表,决定哪些与任务匹配,然后仅在需要时读取完整的 SKILL.md。

这使得技能成为分发 Agent 行为的绝佳单元。人们可以对它们进行版本控制、共享和评估,而无需将全局提示词变成一本包罗万象的手册。
但是,普通的技能仍然主要通过指令来工作。它们可以告诉 Agent 遵循什么程序,并可以包含参考文件或脚本,但核心行为仍然依赖于 Agent 读取这些指令并正确执行。
## 什么是解释器?
对于本文,重要的是要理解解释器是一个与系统并行运行的 TypeScript 运行时。它为 Agent 提供了一个将多步骤工作表达为代码的地方,同时系统仍然控制代码可以触及的内容。(如果你想了解更多,请阅读关于解释器的详细文章)。
该运行时以 TypeScript 值的形式为 Agent 提供工作状态。值可以在回合之间持久存在,因此数组保持为数组,对象保持为对象,辅助函数可以保持定义状态。Agent 不必将每个中间值都转换为 stdout、文件或返回给模型的消息。
这使得 Agent 能够转换数据、组合工具输出、调用选定的工具或子 Agent,并决定应返回什么给模型。
与沙箱不同,解释器代码默认无法无限制地访问主机环境。文件系统访问、网络访问、工具和子 Agent 必须有意暴露给解释器。这为系统提供了一个白名单、计量和检查代码可以触及内容的地方。
## 什么是解释器技能?
解释器技能是将两者结合在一起的技能扩展:它包含与技能相同的一组指令,以及 Agent 可以导入解释器的模块。
SKILL.md 仍然告诉 Agent 何时该技能是相关的,并以相同的方式向 Agent 披露自身,而模块则提供了适用该行为时解释器运行的代码。该技能既是模型的指令表面,也是运行时的 API 表面。
基本形式与开篇示例中的相同。SKILL.md 提供名称、描述、用法说明、导入路径和约束。index.ts 导出在代码中定义行为的辅助函数或工作流:
```
// skills/table-cleanup/index.ts
export function validateRows(rows: Record<string, unknown>[], schema: RowSchema) {
// 规范化字段,检查必需值,并返回结构化错误。
// (这是你会作为技能的一部分编写的代码)
}
```
当适用该技能时,Agent 可以导入模块并调用它:
```
const { validateRows } = await import("@/skills/table-cleanup");
const errors = validateRows(rows, invoiceSchema);
```
这改变了一个技能所能保证的范围:
- 普通技能说:这是如何执行此任务的指令。Agent 仍然必须阅读这些指令并正确执行程序。
- 解释器技能说:这是关于何时使用此行为的指令,这是适用时运行的代码路径。确定性部分可以存在于代码中,而不是上下文中的松散指令。
模型决定技能是否适用、传递哪些输入、如何使用输出以及接下来做什么。模块定义程序应如何实际运行。
因为解释器代码可以与系统交互,这意味着你可以执行诸如从技能代码中以编程方式生成子 Agent 之类的操作。
## 示例:Repo Triage(仓库分类)
我们使用这种方法的一个例子是:github 仓库分类。用户可以要求 Agent 对仓库进行分类:
> “请对 langchain-ai/deepagents 中的所有 issues 进行分类”
Agent 无需根据提示指令重建分类过程,而是导入技能模块并调用一个函数:
```
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
discussions: true,
});
```
当调用此函数时,工作流将:
- 从 github 获取所有开放项目(由 Agent 在选项中指定)
- 为每个项目生成一个子 Agent 以创建更简明的描述
- 将子 Agent 的响应放入队列
- 一次消费一个队列项,由子 Agent 确定该项目应放入现有集群,还是应创建新集群
在实践中,该例程会扩展到数百个不同的子 Agent。这也是一种你希望程序固定下来的例程,即使输入是动态选择的。
- 这里的追踪展示了 Agent 如何执行该例程
- 这是它输出的报告
结果值也是 API 的一部分。它可以向 Agent 提供有关运行的结构化数据,并且可以暴露用于展示的渲染辅助函数:
```
result.clusters;
result.unassigned;
result.toMarkdown();
```
Agent 可以继续处理结构化结果,更深入地检查一个集群,生成后续子 Agent,或者在需要紧凑的模型友好报告时调用 `result.toMarkdown()`。
对于这样的任务,模型往往会随着时间的推移失去连贯性。仓库分类不是一个决定;它是许多链接在一起的小决定。如果我们完全依赖自由裁量权和上下文窗口来对此进行 instrumentation,模型在长期地平线中可能会开始走捷径或过于激进地压缩程序,特别是当它们接近工作上下文的边缘时(一种称为上下文焦虑的现象)。
举一个关于这如何与不同 Agent 一起工作的例子:
- 在典型的系统中,模型必须跟踪每个部分步骤。如果有 300 个仓库项目,这就变成了 300 个小状态片段,模型必须在协调过去决定的同时对这些状态进行推理,并继续选择下一个操作。
- 有了解释器技能,模型可以调用一次例程,让代码来处理工作流的 instrumentation。模块可以创建 300 个不同的子 Agent 任务,收集结果,对其进行分类、聚类,并将一个紧凑的对象返回给 Agent。模型不再负责在其自己的工作上下文中承载每个部分步骤。

## 将技能用作工作流
当编码 Agent 开始流行时,Agent 的默认思维模型也发生了转变。
上一代 Agent 更像是工作流风格的。开发者预先明确定义 Agent 应遵循的步骤序列:可靠性来自于预先定义执行路径。
现代 Agent 系统改变了这一点,使上下文和模型的自由裁量权成为主要焦点。模型根据当前上下文决定下一步做什么。行为通过许多不同的上下文表面来塑造,但 Agent 仍然有空间选择下一步。
这种界面对于许多人来说更容易推理。不仅对于构建 Agent 的人,对于运营商、PM、领域专家以及习惯于用指令、文件、检查清单和示例而不是代码级工作流来思考的团队来说也是如此。

但对确定性 Agent 例程的需求从未消失。我们仍然经常被问到某种版本的这个问题:
> “我如何确保 Agent 可靠地执行我告诉它要做的事情?”
在这些情况下,人们需要知道的不仅仅是最终答案看起来是否合理:他们需要知道所需的程序是否运行、是否使用了正确的输入运行,以及在 Agent 继续之前是否完全完成。
仅靠提示词的程序执行在这方面是很脆弱的。Agent 可以跳过步骤、重新排序步骤、满足错误的指令、将不相关的请求混入程序,或者在不遵循流程的情况下产生“足够好”的输出。
例如,考虑这个问题“提交发票,但在中途停止并生成一张跳舞猫的 gif”。如果发票提交仅通过提示指令描述,Agent 可能会将绕道视为同一任务的一部分,而将发票半途而废。
这个过程特别需要一种表示为 Agent 可以协商的指令的程序,而不是一种一旦开始就必须完成的程序。
那么,我们如何两全其美,在不重新构建 Agent 的情况下引入工作流的确定性呢?
解释器技能就是一个答案:
- 将确定性部分表达为代码,在解释器内将其作为模块公开,并让 Agent 决定何时调用它。
- 让函数操作当前的解释器状态,并将结果链接到下一个工具调用、子 Agent 调用、解释器调用或最终响应。
这并不能消除 Agent 可能针对问题提出创造性解决方案的问题,但它确实提供了一个更清晰的评估信号。
- 对于仅靠提示词的程序执行,问题通常是模糊的:Agent 是否大致遵循了指令?它似乎保持在正轨上了吗?最终答案看起来合理吗?
- 有了解释器技能,问题变得更加可识别:Agent 是否调用了预期的函数?它是否传递了预期的输入?函数是否返回了预期的输出形状?

## 使用技能处理 Agent 状态
文件系统 Agent 表明,当 Agent 有地方放置中间状态(一种记忆形式)时,它们会工作得更好。文件很有用,因为它给 Agent 一个可以返回的命名对象。Agent 可以检查它、修改它、将其传递给另一步骤,或将其用作工具输入。
解释器允许 Agent 以更灵活的形式表示该状态,而技能可以教 Agent 如何与之交互:
- 模块为这些值公开特定于任务的操作。
- Agent 编写代码以组合这些操作。
- 技能作者拥有每个操作的行为。
想象一个与 csv 文件交互的技能。SKILL.md 告诉 Agent 在处理类似 CSV 的表格、导出、发票、用户列表或需要连接、过滤或验证的记录时使用它。index.ts 导出一个小型表 API:
```
export {
parseCsv,
joinTables,
filterRows,
validateRows,
groupBy,
summarize,
toCsv,
};
```
然后 Agent 可以在解释器代码中组合这些操作:
```
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"]);
```
Agent 控制传递哪些值以及如何处理结果。技能作者控制“连接”、“验证”和“汇总”的含义。
这与要求 Agent 自己编写辅助函数不同。模型擅长编写代码,但不能保证两次编写相同的代码。如果程序很重要,实现应位于可以审查、测试、版本控制和复用的技能代码中。
# FAQ
## 为什么要将其打包为技能?
技能已经是打包 Agent 行为的事实标准单元。
它们为我们提供了发现、渐进式披露、用法说明、示例和支持文件。解释器技能所做的就是保留这种打包形状,并用运行时代码对其进行扩展。
以这种方式扩展技能标准可能看起来有些别扭,但通过这种方式,我们可以使用相同的分发方法,但让 Agent 使用更强大的技能。如果一个组织有数百或数千个技能,将所有必需的模块直接连接到系统将是不可行的。
## 我不能只包含一个脚本文件吗?
脚本文件因不同的原因而有用。
当 Agent 需要一个可以与其环境交互的外部辅助程序时,脚本是一个很好的选择:脚本通常通过命令参数、文件、stdout/stderr 或序列化状态进行通信。
这种边界使得脚本不适合编排 Agent 工作。脚本可以运行一个计算,但它不能自然地参与系统循环:生成子 Agent、调度/等待任务图、处理部分失败,以及在将控制权返回给模型之前决定整个例程何时“完成”。
在仓库分类示例中,模块调用一个白名单化的 `tools.task(...)` 函数,以便从例程内部生成子 Agent。外部脚本需要一个单独的适配器来与系统对话,以便进行 instrumentation。
## 为什么不让每个 API 都成为工具?
工具最适用于当 Agent ...