An open-source framework for AI agents

An agent is a folder. That's the whole idea.

OrchaJS defines agents by where files are placed — no orchestration graph, no client to instantiate, no export step. What you run locally is the exact same thing a customer, a teammate, or a no-code dashboard would edit by hand.

~/agents/support-agent

Ownership isn't a contract clause

Most agent platforms ask you to trust that the code you can point to is really running your agent. It usually isn't — the real logic lives inside someone's runtime, and what you get to "export" is a translation of it.

OrchaJS removes the translation step entirely. There's no internal state that isn't also a file. Editing a skill, adding a tool, changing a guardrail — whether by hand or through a dashboard — writes to the same folder a developer would npm install and run standalone.

If a no-code click and a hand-edited file don't produce the same thing, you haven't built ownership — you've built a nicer export button.

What makes the folder the real thing

runtime

A library, not a platform

Add it to Next.js, React, React Native, Express, NestJS, or Node — any JavaScript environment you already use, the way you'd add Prisma or Zod. Orcha compiles to a provider's native format instead of shimming across providers at call time.

tools

Model Action Protocol

What a model can do lives in /actions. Each action is just a folder with two files — no server, protocol handshake, or dependency to install.

actions/
  send-refund/
    index.json   // definition, params, and when to use it
    index.js     // the code that actually runs

index.json tells the model what the action is:

{
  "name": "send_refund",
  "description": "Issues a refund for an eligible order.",
  "params": {
    "orderId": "string",
    "amount": "number"
  }
}

index.js is your code, running in your repo:

export default async function sendRefund(params, ctx) {
  const key = ctx.env.STRIPE_SECRET_KEY;
  // Call Stripe, your API, or your database.
  return { refunded: true, orderId: params.orderId };
}

No MCP server to stand up or integration to configure. If you can write the function, the model can call it.

state

Stateful by default

Tool calls, context, a question waiting on a human — all persisted automatically. Close the tab, restart the process, come back tomorrow: it resumes exactly where it left off. Local by default, or connected to a remote store for cross-device continuation.

guardrails

Policy is a file, not config

Guardrails sit in the folder as a peer citizen, versioned and visible alongside the agent they govern — not hidden in a dashboard's settings panel.

tests

Test cases, run before every release

/tests holds real scenarios with expected behavior, run against every release so a prompt or skill change that breaks something gets caught before it ships.

evaluations

The metrics each run is judged against

/evaluations defines how to score a run — accuracy, tone, or whatever matters for this agent. Passing means something specific, not just "didn't crash."

Two ways to run it

orcha.run() for a single call — structured input to structured output, no session to manage. orcha.agent.run() when the task needs to wait: on a tool, a human, or tomorrow.

// One-shot — no state to think about
const result = await orcha.run('./agents/classifier', input);

// Durable — pause, resume, pick up anywhere
const { sessionId } = await orcha.agent.run(
  './agents/support-agent',
  input
);

// Later, from any process
const next = await orcha.agent.resume(sessionId, humanReply);