@archmax-ai/harness

中文文档
2.0.1发布于 2026/11/03MITTypeScriptES Module构建来源已验证近 30 天下载 5530

Agents can't reliably follow a process. archmax harness makes them: a governed layer over LangChain Deep Agents that enforces a declarative workflow state machine on every step.

原始使用文档
文档目录12 节
  1. Why archmax harness
  2. Install
  3. Quickstart
  4. The workflow
  5. The check
  6. Running it
  7. The CLI
  8. Next
  9. Authoring with a coding agent
  10. Documentation
  11. Development
  12. License

archmax harness

A thin, governed layer over LangChain Deep Agents. Every session runs under a declarative workflow state machine you author in one YAML file.

Why archmax harness

Reliable automation with AI agents should follow the process, and the people who own that process should be able to author it. Today that is out of reach for most domain experts. Current automation tools fall short in three ways.

  • The agent is a step, not the process. The agent sits inside a fixed graph, so its flexibility ends at the edge of one node. The process stays as rigid as the diagram someone drew.
  • The process and its implementation drift apart. Every business process is restated as a technical graph. That makes two artifacts with two owners, and keeping them in step never stops costing effort.
  • Complex data still ends up in code. Nested payloads, loops and arithmetic land in a code node. The person who owns the process cannot read it, let alone change it.

The archmax harness turns this around. The agent runs the whole process, and one workflow.yaml both describes it and enforces it. Data work happens in a sandbox the same rules govern.

Full documentation: https://harness.archmax.ai/

Install

npm install @archmax-ai/harness

Node 22 or later. The model is configured through the environment, against any OpenAI-compatible endpoint. The archmax harness reads those keys from a .env in the workspace root:

ARCHMAX_API_BASE_URL=https://api.example.com/v1
ARCHMAX_API_KEY=...
ARCHMAX_MODEL=...

ARCHMAX_MODEL is the default. A workflow names the id its states run on with settings.model, and a single state overrides that with its own model:. Either way it is an id, resolved over the same endpoint and credentials. So a mechanical state can run on a small model while the state whose output a person reads runs on a capable one.

See configuration for every variable.

To have a coding agent (Claude Code, Cursor, Codex, …) author workflows for you, install the authoring skill:

npx skills add archmax-ai/harness

Quickstart

A refund desk in four states. The agent decides the refund and drafts the email, a script checks the decision against the policy, a grader checks the email, and the agent sends it. The complete example is in examples/refund/.

refund/
├── index.js                          # your program: the host tools and the agent
├── tools.js
└── workflows/refund/
    ├── workflow.yaml                 # the process, enforced
    └── scripts/check-decision.js     # the deterministic check

The workflow

# workflows/refund/workflow.yaml
title: Refund request
instructions: Decide only from what lookup_customer returns; never guess an order.

states:
  decide:
    triggers:
      manual:
        requires: [email]
    tools:
      allow: [lookup_customer]
    instructions: >-
      Look the customer up with lookup_customer, using the `email` variable. A
      refund is approved only when their order is delivered; otherwise it is
      denied. Record the decision with archmax_set_variables as `decision`
      (approved or denied), write the email to the customer in
      scratchpad/email.md, then advance to check-decision. If you are sent
      back, fix what the note says and advance again.
    transitions:
      - to: check-decision
        description: The decision is recorded and the email is drafted.

  check-decision:
    type: code
    script: scripts/check-decision.js
    tools:
      allow: [lookup_customer]
    transitions:
      - to: review-email
        description: The decision matches the refund policy.
      - to: decide
        description: The decision contradicts the refund policy.

  review-email:
    type: grader
    instructions: >-
      Read scratchpad/email.md and the `decision` variable. Approve the email
      when it is polite, states the decision plainly and names the order.
      Otherwise send it back, saying exactly what to change.
    transitions:
      - to: send
        description: The email is ready to send.
      - to: decide
        description: The email needs changes.

  send:
    tools:
      allow: [send_email]
    instructions: >-
      Send scratchpad/email.md to the customer at `email` with send_email, then
      say in one sentence that it was sent.

Each state is one step of the process, and the agent only ever sees the step it is in: that state's instructions, its tools and the transitions out of it, each described so it can choose between them. It moves on by calling archmax_advance, and the runtime refuses any edge the state does not declare. A state with no transitions, like send, is where the session ends.

Two of the states run without the agent. check-decision is a code state: the runtime runs its script on entry, with no model call. review-email is a grader state: an isolated subagent judges the email against the state's instructions. Both reach only their own state's tools, and both decide the same way the agent does, with archmax_advance. A send-back reaches the agent as a note it reads before trying again.

The check

// workflows/refund/scripts/check-decision.js
/** A refund is due only for a delivered order: any other decision goes back to the agent. */
export default async function ({ variables, tools }) {
  const customer = JSON.parse(await tools.lookup_customer({ email: variables.email }));
  const order = customer?.order;
  const due = order?.status === "delivered" ? "approved" : "denied";

  if (variables.decision === due) {
    await tools.archmax_advance({
      to: "review-email",
      reason: `The refund is ${due}, as the policy requires.`,
    });
  } else {
    await tools.archmax_advance({
      to: "decide",
      reason: `Order ${order?.id ?? "(none)"} is ${order?.status ?? "unknown"}, so the refund must be ${due}.`,
    });
  }
}

The policy lives in code, so it holds whatever the model says. When the agent records the wrong decision, the script sends it back with the reason, before anyone grades the email.

Running it

npm install @archmax-ai/harness langchain zod

lookup_customer and send_email are your systems, passed in as ordinary LangChain tools:

// tools.js
import { tool } from "langchain";
import { z } from "zod";

const customers = {
  "[email protected]": { name: "Ann", order: { id: "ORD-1001", status: "delivered" } },
  "[email protected]": { name: "Bob", order: { id: "ORD-1002", status: "shipped" } },
};

export const lookupCustomer = tool(async ({ email }) => JSON.stringify(customers[email] ?? null), {
  name: "lookup_customer",
  description: "Look up a customer and their latest order by email address.",
  schema: z.object({ email: z.string() }),
});

export const sendEmail = tool(
  async ({ to, body }) => {
    console.log(`To ${to}:\n${body}`);
    return "sent";
  },
  {
    name: "send_email",
    description: "Send an email to the customer.",
    schema: z.object({ to: z.string(), body: z.string() }),
  },
);
// index.js
import { createAgent } from "@archmax-ai/harness";
import { lookupCustomer, sendEmail } from "./tools.js";

const agent = await createAgent({
  workflow: "refund",
  tools: [lookupCustomer, sendEmail],
  workspace: { rootDir: import.meta.dirname },
});

const outcome = await agent.workflow.send("ticket-1001", {
  message: "Hi, I'd like a refund for my last order.",
  variables: { email: "[email protected]" },
});

console.log(outcome.kind); // "completed"
console.log(outcome.auditTrail.map((step) => `${step.kind} → ${step.to}`).join("\n"));
completed
trigger → decide
agent → check-decision
code → review-email
grader → send

One call is one turn, and outcome says how it ended: completed, parked (waiting on a person or an event), or failed (the agent called archmax_raise because the work cannot be done). The trail records every move and who made it. Sessions are durable, under sessions/ by default, so send with the same id continues the conversation.

The CLI

A workflow that needs only the harness's own tools runs from the command line too. The reference workspace examples/customer-support/ is one, and it is the suite the end-to-end tests run against a real model:

npx archmax run order-lookup "Which orders are delayed for Acme?" --root examples/customer-support
npx archmax test order-lookup --root examples/customer-support       # run the workflow's cases
npx archmax validate order-lookup --root examples/customer-support   # static checks, no model calls

The refund example needs your two tools, so it runs from your code. See the CLI reference for sessions, decide, reply and deliver.

Next

Authoring with a coding agent

The authoring skill teaches a coding agent the schema, grader and code states, governance, human states, cases and the CLI. Install it with the skills CLI:

npx skills add archmax-ai/harness

That installs the latest version from GitHub. To pin the skill to the SDK version your project depends on, install the copy shipped inside the package instead, after npm install:

npx skills add ./node_modules/@archmax-ai/harness

For skills middleware in your own agent, the BUNDLED_AUTHORING_SKILL_DIR export resolves to the packaged copy. The source is skills/archmax-harness/.

Documentation

Development

npm run dev -- run order-lookup "..." --root examples/customer-support
npm run typecheck && npm test
npm run docs:dev

Substantive changes flow through OpenSpec under openspec/. Documentation, README.md and the authoring skill ship in the same change as the behaviour they describe. See CONTRIBUTING.md and the development setup.

License

MIT. See LICENSE.

版本与发布记录

@archmax-ai/harness 共发布 22 个版本,首次发布于 2026/09/24;过去 12 个月发布了 22 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.0.1latest2026/11/034 天前
2.0.02026/10/308 天前
1.1.02026/10/308 天前
1.0.12026/10/2513 天前
1.0.02026/10/2414 天前
0.9.02026/10/2315 天前

关于 @archmax-ai/harness 的常见问题

@archmax-ai/harness 是什么?

Agents can't reliably follow a process. archmax harness makes them: a governed layer over LangChain Deep Agents that enforces a declarative workflow state machine on every step.

如何安装 @archmax-ai/harness?

在项目目录运行 npm install @archmax-ai/harness,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 archmax,可以用 npx archmax 直接运行。

@archmax-ai/harness 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@archmax-ai/harness 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@archmax-ai/harness 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@archmax-ai/harness 可以商用吗?

@archmax-ai/harness 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@archmax-ai/harness 的下载量有多少?

根据 npm 官方下载统计,@archmax-ai/harness 在 2026/10/07 – 2026/11/05 这 30 天内被下载 5,530 次,日均约 184 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@archmax-ai/harness 还在维护吗?

最新版本 2.0.1 发布于 2026/11/03(4 天前);至今共发布 22 个版本,其中过去 12 个月发布了 22 个;首次发布于 2026/09/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。