npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agent-orc/harness-protocol

v2.0.0

Published

Orca Harness Protocol v1 server library: write the agent, not the wire

Readme

@agent-orc/harness-protocol

A server library for Orca Harness Protocol v1.

A harness is your own agent-worker. Orca's runtime (agent-runtime) boots it per session and drives it over exactly the contract the platform's built-in sidecar answers, so it drops into the same socket: same /health, /healthz, /run, /state, and /models.

This library is that contract. It handles routing, NDJSON framing, event ordering, cancellation, request limits, state transfer, and connecting the session's MCP tools. You write the agent loop.

Terminology, because it is easy to get backwards: the agent is a profile you configure in Orca, and one harness serves many of them. The harness is the worker that runs them. There is only one runtime, and it is Orca's.

It is not a harness framework and not a set of agent-SDK adapters. There is no piAdapter(). You import your SDK directly and map its events onto ctx.emit, which is about fifteen lines and leaves you in control of the loop.

Your SDK code  +  @agent-orc/harness-protocol  =  a conformant harness

Install

npm install @agent-orc/harness-protocol

The shape

import { createHarnessServer, type RunContext } from '@agent-orc/harness-protocol'

const harness = createHarnessServer({
  // What this worker calls itself, reported as `runtime` in /health, exactly
  // as the platform sidecar reports MODE=claude there. Not an agent name:
  // agents are Orca profiles, and this one worker serves all of them.
  harness: 'ledger-harness',

  // Optional. Surfaces at GET /models, which is what fills the model picker
  // in the Orca dashboard.
  models: ['anthropic:claude-sonnet-4-5', 'openai:gpt-4o'],

  async run(ctx: RunContext) {
    ctx.emit.progress('reading the ledger')
    ctx.emit.assistant('I found three unmatched lines.')
    return 'Reconciled 3 of 3.'
  },
})

await harness.listen({ port: Number(process.env.PORT ?? 7099) })

That is a conformant harness. Everything below is optional detail.

With an agent SDK

Pi, as a worked example. The pattern is the same for any SDK: create the session, map the generic tools into whatever your SDK calls a tool, forward text and usage to ctx.emit, and return the answer.

import { createHarnessServer, type RunContext } from '@agent-orc/harness-protocol'
import {
  createAgentSession,
  ModelRuntime,
  SessionManager,
  type ToolDefinition,
} from '@earendil-works/pi-coding-agent'

const models = await ModelRuntime.create()

const harness = createHarnessServer({
  harness: 'ledger-harness',

  async run(ctx: RunContext) {
    // Already split, and leniently: an un-namespaced id leaves provider
    // undefined, which is how claude and codex profiles are written.
    const model = models.getModel(ctx.model.provider ?? 'anthropic', ctx.model.modelId)
    if (!model) throw new Error(`unknown model: ${ctx.model.id}`)

    // ctx.tools is generic. This is where a Pi harness makes it Pi's. Pi types
    // parameters as a TypeBox TSchema (a JSON Schema object at runtime) and
    // wants a content array back rather than a bare value.
    const customTools: ToolDefinition[] = ctx.tools.map((tool) => ({
      name: tool.name,
      label: tool.name,
      description: tool.description,
      parameters: tool.inputSchema as unknown as ToolDefinition['parameters'],
      async execute(toolCallId: string, params: unknown) {
        const output = await tool.call(params, { toolCallId })
        return {
          content: [{ type: 'text' as const, text: String(output) }],
          details: undefined,
        }
      },
    }))

    const { session } = await createAgentSession({
      model,
      modelRuntime: models,
      sessionManager: SessionManager.inMemory(),
      tools: customTools.map((t) => t.name),
      customTools,
    })

    ctx.signal.addEventListener('abort', () => void session.abort(), { once: true })

    session.subscribe((event) => {
      if (event.type === 'message_update' && event.assistantMessageEvent?.type === 'text_delta') {
        ctx.emit.assistant(event.assistantMessageEvent.delta)
      }
      if (event.type === 'message_end' && event.message?.usage) {
        ctx.emit.usage({
          inputTokens: event.message.usage.input ?? 0,
          outputTokens: event.message.usage.output ?? 0,
        })
      }
    })

    await session.prompt(ctx.subtask.prompt)

    return {
      message: finalText(session.agent.state.messages),
      state: { messages: session.agent.state.messages },
    }
  },
})

await harness.listen({ port: Number(process.env.PORT ?? 7099) })

orca harness init --sdk pi writes a working version of this.

What you get

ctx

| Field | What it is | |---|---| | ctx.subtask.prompt | The work to do. | | ctx.model | profile.model split into { id, provider?, modelId, supported }. | | ctx.profile | name, runtime, model, systemPrompt, tools, template. | | ctx.tools | Platform and user MCP tools, already connected. Always an array. | | ctx.skills | Resolved skill documents. Use these; never read the host filesystem. | | ctx.state | Whatever the previous run returned as state, or undefined. | | ctx.signal | Aborts when the platform cancels. Thread it into model and tool calls. | | ctx.emit | progress, assistant, usage, session, toolCall, toolResult. | | ctx.request | The raw envelope, for anything this version does not surface. |

ctx.tools

Every MCP server in the envelope is connected before run is called, and their catalogs are flattened into one list. Names are prefixed mcp__<server>__ so two servers exporting search cannot collide.

type HarnessTool = {
  name: string
  description: string
  inputSchema: Record<string, unknown>   // JSON Schema
  call(input?: unknown, opts?: { toolCallId?: string }): Promise<unknown>
}

call emits a tool_call before and a tool_result after, so tool use shows up in the Orca transcript without you reporting it. It resolves with structured output when the tool provides it, otherwise the joined text.

Pass tools: false to skip connecting, if your harness brings its own.

Returning

return 'the answer'                                  // stateless
return { message: 'the answer', state: { ... } }     // stateful

The state value comes back as ctx.state on the next run for that session, including after Orca has moved the session to a different replica. It must be JSON-serializable and under 8 MB.

Models

models is declarative. It answers GET /models in the shape the conductor decodes, which is how a tenant's models reach the dashboard picker:

{ "runtimes": { "ledger-harness": ["anthropic:claude-sonnet-4-5"] }, "errors": {} }

Declare nothing and the route does not exist, which is the sidecar's own convention: the conductor drops an upstream it cannot reach, where an empty 200 would be taken as authoritative and blank the picker.

The library never refuses a run over it. Orca does not validate the model on a custom-runtime profile either, so rejecting one here would make your harness stricter than the worker it replaces and fail runs the profile was legal for. ctx.model.supported tells you; what to do is yours:

if (!ctx.model.supported) ctx.emit.progress(`${ctx.model.id} is untested here`)

What the library guarantees

These are the parts of the spec that are easy to get wrong by hand, and the reason this exists rather than a copy-pasted server.ts:

  • Exactly one terminal event per run, always last. Anything emitted after it is dropped rather than corrupting the stream.
  • A client disconnect aborts ctx.signal and does not take the process down. A run that finishes normally does not abort, which is the bug most hand-written harnesses ship.
  • A malformed envelope is a 400 before the stream opens, never an error event on a 200.
  • GET /state/{id} answers 404 when nothing is stored. That is the correct stateless answer, not a failure.
  • Request bodies and state bundles are capped rather than buffered without limit, and /health stays under the 64 KB the platform reads.
  • MCP servers are closed when the run ends, including when connecting one of them failed part-way through.
  • /healthz answers as well as /health, and /models appears only when you declare models, both matching the platform sidecar.

Security

The platform never sends its own credentials to a harness. The only authority a run carries is the session-scoped MCP endpoint in its envelope. Model provider credentials belong to you, and reach the harness through its own environment.

Tenant-declared MCP server URLs get a scheme and literal-address check before connect: loopback, RFC1918, link-local, and the cloud metadata address are refused. This is defense in depth, not the authority, because it runs before DNS resolution. Set HARNESS_ALLOW_HOSTS=localhost for local development.

Conformance

node index.ts &
./conformance.sh http://localhost:7099

The checker lives in the platform repo at examples/brains/conformance.sh. It exercises the wire behaviors a unit test cannot see. This library passes all 15 checks with no skips.

Versioning

The package version and the wire version are independent. @agent-orc/harness-protocol@2 may still speak orca-harness/v1. Do not infer protocol compatibility from an npm version.