@agentworkforce/harness-kit (英语)
用于产出人带(Claude, codex, opencode),带有其MCP服务器,env vars,并且权限连接正确.
这是层 @agentworkforce/cli 坐于顶上. 狦琌
搭建你自己的管弦乐团 @agentworkforce/workload-router
并且想要CLI提供的相同行为——env-ref分辨率,MCP
隔离、权限旗帜翻译——取决于此软件包而不是
重新实施这些建议.
路由器( R)
@agentworkforce/workload-router) 型号 什麽 一个人a 没错 这个工具箱模型 如何发射 在给定的绳子上。 两者都是 单靠自己掌握着不可知的知识; 穷困的知识就在这里.
安装
pnpm add @agentworkforce/harness-kit @agentworkforce/workload-router
盒子里的东西
buildInteractiveSpec(input) ——将人物a 翻译为交互式 argv
夺去田地 a PersonaSelection (病情,模型,系统Prompt,
设置、 mcpServers、 权限)和返回
{bin, args, initialPrompt, warnings}。 。 。 .
纯粹——没有I/O,没有stderr写作. 警告已返回, 您的呼叫路径
只要有道理,他们就去.
import { resolvePersona } from '@agentworkforce/workload-router';
import {
buildInteractiveSpec,
resolveMcpServersLenient,
resolveStringMapLenient,
formatDropWarnings
} from '@agentworkforce/harness-kit';
import { spawn } from 'node:child_process';
const selection = resolvePersona('persona-authoring');
// Resolve env + MCP refs against the current process environment. Missing
// refs don't throw — they come back on `.dropped` so you can warn the user.
const envResolution = resolveStringMapLenient(selection.env, process.env, 'env');
const mcpResolution = resolveMcpServersLenient(selection.mcpServers, process.env);
const warnings = formatDropWarnings(
envResolution.dropped,
mcpResolution.dropped,
mcpResolution.droppedServers
);
for (const w of warnings) console.warn(w);
// Build the exec spec.
const spec = buildInteractiveSpec({
harness: selection.runtime.harness,
personaId: selection.personaId,
model: selection.runtime.model,
systemPrompt: selection.runtime.systemPrompt,
harnessSettings: selection.runtime.harnessSettings,
mcpServers: mcpResolution.servers,
permissions: selection.permissions
});
for (const w of spec.warnings) console.warn(w);
// Spawn the harness.
const args = spec.initialPrompt ? [...spec.args, spec.initialPrompt] : [...spec.args];
spawn(spec.bin, args, {
stdio: 'inherit',
env: { ...process.env, ...(envResolution.value ?? {}) }
});
useRunnablePersona(intent) ——以非互动方式管理一个人
给需要节目的主持人 sendMessage() 水面,工具箱
也暴露出一个在同一个路由器+取用翻译路径周围的瘦跑者.
它能解决人的问题a, 以非交互方式发射选中的带子
模式, 抓取 stdout/stderr, 报告进度块, 支持取消
并返回稳定的执行结果.
useRunnablePersona 遵循路由器的内部内置解析器。 对于
选项包/本地人,解析 a PersonaSelection 通过您的来源
级联和呼叫 useRunnableSelection(selection)。 。 。 .
import { useRunnablePersona } from '@agentworkforce/harness-kit';
const persona = useRunnablePersona('persona-authoring');
const run = persona.sendMessage('Draft a persona for workflow artifact writing.', {
workingDirectory: process.cwd(),
name: 'persona-author',
timeoutSeconds: persona.selection.runtime.harnessSettings.timeoutSeconds,
inputs: {
TARGET_DIR: '.agentworkforce/workforce/personas',
CREATE_MODE: 'local',
TASK_DESCRIPTION: 'Write a workflow artifact as structured JSON.'
},
onProgress: (chunk) => process.stderr.write(chunk.text)
});
const result = await run;
if (result.status !== 'completed') {
throw new Error(result.stderr || `persona run failed: ${result.status}`);
}
console.log(result.output);
如果选中的人a 声明 inputs, (中文(简体) ), sendMessage(..., { inputs })
在产卵前解决这些值,代用品 $NAME 编号 : ${NAME} 输入
系统提示,并将解析后的值注入到子进程内.
明确使用分辨率 inputs,则 process.env[spec.env ?? NAME],则
default,当需要的输入仍未被设定时丢出.
跑道图利用它们的非交互命令形状:
claude --print, (中文(简体) ), codex exec,以及 opencode run。它会生成
配置文件, 如 opencode.json 仅限儿童持续期间
处理,然后恢复或删除。 技能安装是选入
与 installSkills: true; 需要加强文件系统隔离的呼叫者
应在跑道周围继续使用挂载/沙箱层.
Claude 牵引保障
何时 harness === 'claude', (中文(简体) ), buildInteractiveSpec 永远 既发出:
--mcp-config '{"mcpServers": …}'——即使为空--strict-mcp-config——迫使克洛德代码忽略用户/项目MCP来源
这意味着人物会话只看到 MCP 服务器本身
声明 ~/.claude.json 和任何项目 .claude/ MCP 配置为
在会话中看不见 这就是人被隔离的整个点;
如果您想要在会话中填写个人MCP,请在人物上声明.
编码/ 打开代码
目前状态: 这些带子不会暴露运行时间MCP注射或
允许控制他们的CLI. buildInteractiveSpec 携带
系统作为初始位置提示 [PROMPT] 参数(自
也没有 --system-prompt 并返回警告字符串,如果
声明 mcpServers 或者说 permissions。打电话者决定是否
以打印、失败或继续.
信封参考分辨率
该套件支持两种形式的人体内的env参考a JSON:
| 表单 | 语义 |
|---|---|
"$VAR" | 全程参考. 整个值被替换 . |
"Bearer ${VAR}" | Braced; 每个 ${VAR} 已插入内插. |
未擦伤 $VAR 中字符串 以字面形式保存——这防止了流浪者
$ 在JSON值中,因为意外被作为参考
继续指向特定字段名称的缺失- var 错误.
两项解决政策
选择符合您错误处理偏好的一个 :
| 函数 | 缺少参考文献 | 使用时间 |
|---|---|---|
makeEnvRefResolver(env) 编号 : resolveStringMap(map, env, prefix) | 掷出 MissingEnvRefError | 您想要失败快取 — 例如 CI 脚本, 其中缺失的秘密是配置错误 . |
makeLenientResolver(env) 编号 : resolveStringMapLenient(map, env, prefix) | 返回时 {ok:false, field, ref} (或将条目放在 Lenient 地图帮助器) | 您想要优雅的回落——比如,如果熊鼠指号没有设置,允许一个MCP服务器通过OAuth认证. |
CLI 使用宽放路径; 它会丢弃缺少的env 条目和未设定的 MCP
带有警告的页眉,只有在出现 结构 字段 (url, (中文(简体) ),
command,任意 arg)无法解决.
人物输入渲染
Persona投入与env参考不同。 输入可快速可见
在个人上声明的运行时间值, 例如 TARGET_DIR, (中文(简体) ), PACKAGE_NAME,或
CREATE_MODE。用于非秘密发射上下文,而不是 API 密钥.
import { renderPersonaInputs, resolvePersonaInputs } from '@agentworkforce/harness-kit';
const { values } = resolvePersonaInputs(
{
TARGET_DIR: { env: 'MY_TARGET_DIR', default: './out' },
CREATE_MODE: { default: 'local' }
},
{ TARGET_DIR: '/tmp/personas' },
process.env
);
const systemPrompt = renderPersonaInputs(
'Write to $TARGET_DIR using ${CREATE_MODE} mode.',
values
);
resolvePersonaInputs 缺少所需的输入失败 。 这是
故意: 与秘密内存 refs 不同,输入通常是结构上下文
人需要遵守合同.
API 表面
// Persona inputs
export class MissingPersonaInputError extends Error { input: string; env: string }
export function resolvePersonaInputs(inputs, provided, processEnv): PersonaInputResolution
export function renderPersonaInputs(systemPrompt, values): string
export interface PersonaInputResolution { values: Record<string,string> }
export type PersonaInputValues = Record<string, string | number | boolean | null | undefined>
// Env refs
export class MissingEnvRefError extends Error { ref: string; referencedBy: string }
export function makeEnvRefResolver(env): (value, field) => string
export function makeLenientResolver(env): (value, field) => LenientResult
export function resolveStringMap(map, env, prefix): Record<string,string> | undefined
export function resolveStringMapLenient(map, env, prefix): { value, dropped: DroppedRef[] }
export type LenientResult = { ok: true; value: string } | { ok: false; field: string; ref: string }
export interface DroppedRef { field: string; ref: string }
// MCP
export function resolveMcpServersLenient(servers, env): McpResolution
export function formatDropWarnings(envDrops, mcpDrops, mcpServerDrops): string[]
export interface McpResolution {
servers: Record<string, McpServerSpec> | undefined;
dropped: DroppedRef[];
droppedServers: DroppedMcpServer[];
}
export interface DroppedMcpServer { name: string; refs: string[] }
// Harness
export function buildInteractiveSpec(input: BuildInteractiveSpecInput): InteractiveSpec
export interface BuildInteractiveSpecInput {
harness: Harness;
personaId: string;
model: string;
systemPrompt: string;
harnessSettings?: HarnessSettings;
mcpServers?: Record<string, McpServerSpec>;
permissions?: PersonaPermissions;
}
export interface InteractiveSpec {
bin: string;
args: readonly string[];
initialPrompt: string | null;
warnings: string[];
}
// Runnable personas
export function useRunnablePersona(intent, options?): RunnablePersonaContext
export function useRunnableSelection(selection, options?): RunnablePersonaContext
export interface RunnablePersonaContext {
selection: PersonaSelection;
install: PersonaInstallContext;
sendMessage(task, options?): PersonaExecution;
}
export interface PersonaExecutionResult {
status: 'completed' | 'failed' | 'cancelled' | 'timeout';
output: string;
stderr: string;
exitCode: number | null;
durationMs: number;
}
状态
小型而稳定的地表 专注于三件事 一个带子产卵者需要:
解析 env refs, 解析 MCP 配置并构建 argv 。 默认导出为
使用时仍然是纯的 buildInteractiveSpec 直接说 这个
useRunnablePersona 方便是故意的 小小的副作用
给消费者的一层,他们想要同样的绳子知识 加上捕捉到的知识
非互动性儿童过程.