HarnessRouter Community Edition - Open-source unified interface for agent harnesses

Plug-and-play managed agent harnesses in your product: Codex, Claude Code and Hermes through one API on your infrastructure, now open sourced under Apache 2.0. Switch harnesses without rebuilding your backend. Sessions, streaming, files, artifacts, cancellation, failure recovery, all handled. Model provider keys, state, and deliveries under your control. Gateway, Runner, Console in one Docker container. Ready-to-use starter kit apps as inspiration of possibilities.

Add a comment

Replies

Best

Hey Product Hunt 👋

Today we're launching HarnessRouter Community Edition. Think of us as OpenRouter, but for agent harnesses instead of models.

We built HarnessRouter because we used to rebuild the same backend every time we need an agent runtime behind a product. We used to build our own harness with LangGraph, agent SDK, pydantic, etc, just to find out our self-built harness performance is hard to compete with Codex, Claude Code, Hermes, etc. Once we switched our infra to leverage off-the-shelf harnesses instead of rebuilding, our agent feature delivery time is shortened from weeks to hours, and the agent quality is dramatically better. We want to advocate the same mindset to the builder community.

HarnessRouter Community Edition puts Codex, Claude Code, and Hermes behind a single API: sessions, streaming, files, artifacts, cancellation, and all the failure handling nobody enjoys writing. Pull and start with one Docker container. Your credentials, state, and files never leave your infrastructure.

In addition to the product itself, we are also publishing Unified Harness Protocol. The Unified Harness Protocol standardizes how an application talks to an agent harness. The protocol covers harness selection and configuration, task execution, streaming events, sessions, file management, cancellation, error handling, and result delivery.

One more thing: harness agents are good at far more than coding. We're shipping open source starter kits across a bunch of agentic use cases (PPT building, Spreadsheet creating, BI/Dashboard creating, Video editing, etc). The use cases we're most curious about are the ones we haven't thought of.

We would love to learn two things from ProductHunt community:

  1. Which harness should we support next?

  2. Where does the abstraction leak for what you're building?

We're around all day.

 Nice launch Congrats🙌 loving the clean UI and vision here, How are you guys handling data privacy and local vs. cloud processing under the hood?

 Thank you for your support, Priya!

To answer your data privacy question: Community Edition runs entirely on your infrastructure, keeping everything under your control, while HarnessRouter Cloud manages the infrastructure and operations for you.

Rebuilding agent harnesses from scratch is definitely a huge pain point, so unifying Codex, Claude Code, and Hermes behind a single API is super smart. Self-hosting via Docker while keeping credentials local is a big plus. Are you planning to add support for AutoGen or CrewAI harnesses next?

 Thanks! Great question, and it gets at a distinction we think about a lot. AutoGen and CrewAI are frameworks: you use them to build your own agent. Codex, Claude Code, and Hermes are harnesses: complete, packaged agent runtimes with their own planning, tool use, and recovery behavior built in. HarnessRouter routes to harnesses, so the near term roadmap is more of those (tell us which ones you want!). That said, the interesting bridge is the Unified Harness Protocol: if you've built an agent with CrewAI or AutoGen and wrap it in a UHP conformant interface, it can sit behind the same API as everything else. So rather than us shipping a specific AutoGen integration, we'd love to see framework built agents join as harnesses through the open spec.

 great question!  great answer! UHP is an open protocol, and we welcome all harness developers and industry players to contribute to and shape together: . Frameworks used to be small, granular building blocks that most developers had to learn. UHP and HarnessRouter help them stop worrying about that, since they now have larger, fully featured building blocks.

   This is a visual illustration of what I mean by saying: UHP and HarnessRouter help them stop worrying about that, since they now have larger, fully featured building blocks.

 Congrats on the launch! Open sourcing this is a strong move. We ship agent-powered products and the "one API, swap the harness" idea is exactly the abstraction we ended up building badly in-house. Question: how do you handle harness-specific capabilities that don't map 1:1 across Codex / Claude Code / Hermes lowest common denominator, or escape hatch to the native layer?

 Thanks Lorenzo, this is THE design question for an abstraction like this, so let me answer from what's actually in the spec rather than hand waving. We deliberately didn't go lowest common denominator; UHP is layered.

First, the uniform task surface: sessions, streaming, files, artifacts, cancellation, structured errors. That's the portable core, and it's what the conformance suite enforces with real agent tasks, not schema checks (a stream that never flushes or a cancel that returns 200 while the agent keeps running are invisible to schema validation).

Second, capability discovery is first class. Every UHP server serves a discovery document at /v1/uhp with named capability booleans (sessions, cancellation, file input and output, harness management, idempotency...). Servers must report false rather than omit, so a client can distinguish "not supported" from "server predates this field." No learning from 404s. Fun fact: missing capability discovery was literally the first defect the conformance suite caught in our own reference implementation.

Third, harness differences live at the config layer, not the wire. The harness base is an opaque string, deliberately not enumerated by the spec, so next year's harness doesn't require a protocol revision. And where runtimes genuinely differ, the spec documents the latitude instead of pretending uniformity: disabling a tool is a hard deny rule in Claude Code but an instruction to Codex, and the spec permits both and says which guarantee you're getting.

Fourth, the escape hatch: extensions are additive and documented (metadata, a small number of extra fields, additional object types), never a redefinition of an existing field, and the schemas are open. A client that ignores every extension still gets a working task. The suite only enforces what the spec says, so anything our implementation does beyond it stays clearly labeled as HarnessRouter behavior, not accidental protocol.

Would love to hear which specific capabilities bit you when you built this in house, that's exactly the feedback that decides what gets promoted into core.

   Great discussion! Extensibility is essential for any open industry standard. That’s why we designed UHP as a layered, modular protocol, with a shared portable core and additive extensions for harness-specific capabilities.

I really enjoyed this exchange. Conversations like this are what move industry standards forward. We’d love to have you join the and help shape with us.

💎 Pixel perfection
Thanks both. Count me in on the community. What bit us in house, briefly. The biggest one is exactly your Claude Code deny rule vs Codex instruction example. We ship conversational agents, and every constraint we wrote as an instruction to the model was advisory. It held most of the time and failed precisely when it mattered. Nothing got reliable until we moved those constraints out of the prompt into a config layer the runtime enforces. So what I want from discovery is not only whether a capability exists, but what strength of guarantee comes with it, enforced by the runtime or best effort, plus a way to require the hard version and fail loudly instead of silently degrading. The second one is staleness. Our worst bugs were never a wrong capability set, they were an old one. Content refreshed live while the capability list was fixed at connection time, so clients kept running against a set that had already changed. Does the spec say anything about the lifecycle of the /v1/uhp document, caching, invalidation, or what a client should assume if the server comes back with a different set mid session? That feels like the distance between discovery existing and discovery being trustworthy. Also fully agree on running real tasks in the conformance suite rather than schema checks. The failures that hurt are the ones that look correct on the wire.

   Honestly, you found two real gaps, so I'll just say that plainly. On guarantee strength: capabilities today are plain booleans, and the enforced vs advisory distinction lives in spec prose, not in discovery. Your version is better. We've been bitten by exactly what you describe: constraints that hold most of the time and fail when it matters (we found a "hard" tool block that was silently advisory, it's written up in the conformance report). So I want strength per capability in the spec, not just fixed in our code. On staleness: the spec is currently silent on the discovery document's lifecycle. A session can't silently change harness (409 harness_mismatch) and version is pinned per request, but "what does a client assume if the capability set changes mid session" is genuinely unspecified. You're right that that's the gap between discovery existing and discovery being trustworthy. We will file both as issues, spec changes land with a conformance check attached, so they won't die as thread ideas. And glad you joining our community, bring exactly this energy!

   The prompt-vs-runtime trade-off is almost a philosophical one. From my experience building harnesses, if an issue is likely to improve as models get better, I usually leave it to the prompt unless the constraint is critical. This avoids adding rapidly growing complexity to the runtime, or building temporary infrastructure that may soon become obsolete as models evolve.

I really like your point that capability discovery should communicate the strength of each guarantee. Whether fallback is allowed, or the system must fail loudly, is essential to whether teams can trust the product with important tasks.

Your insight about stale capability information is excellent as well. We are honored to have you join the community and help shape and the with us.

 Congratulations on the launch! 🎉 HarnessRouter is a really interesting approach to making different agent harnesses more accessible through a single API. One question: how are you thinking about handling the differences in capabilities and behavior between Codex, Claude Code, and Hermes while keeping the harness abstraction consistent?

 Thank you Kamal! We normalize the lifecycle, not the harness. What every harness shares (sessions, streaming, files, cancellation, structured errors) is the uniform surface the conformance suite enforces. What differs is made explicit instead of hidden: every server declares its capabilities in a discovery document, fail closed, so apps can detect and branch rather than assume, and harness specific behavior stays at the config layer instead of being flattened into a lowest common denominator. Where runtimes genuinely differ in guarantees, the spec documents the difference rather than pretending uniformity. There's a deeper exchange on exactly this in the thread with and if you want the details, including the gaps they found that are becoming spec proposals. The abstraction stays consistent because it standardizes how you drive a harness, never how the harness thinks.

Since its opensource. Its meant to be forked and customized I suppose? And since its a composition product, a product with many parts, how composable is it? how easy is it to swap out parts of the system for my own when I want to change things etc? Recently DeepSeek launched their harness as opensource. 100k stars in 2 days etc. And the code was modeled on a composable plugin architecture of sorts ref what are your thoughts around this? Thanks!

 Great question André! And yes, we've been watching the dsh launch closely (the Cordis paper is genuinely interesting work on revertible effects / hot-swap composability).

The way we think about it: dsh and HarnessRouter are composable at different layers. dsh makes the internals of one harness swappable: model adapter, tool registry, agent loop, all plugins. HarnessRouter makes harnesses themselves swappable: you integrate one API (UHP), and you can route each task to Codex, Claude Code, Hermes, and soon Pi, dsh and more, without rebuilding your backend. UHP is a versioned open spec (OpenAPI 3.1 + JSON Schema, 47 runnable conformance checks), so if you want to swap in your own harness implementation, or fork ours, the contract is public and independently testable. That's where the fork-and-customize story lives.

On plugin-level flexibility: it's always a trade-off between composability, customizability, and ease of use. Our bet is that the frontier labs and the best harness teams will keep their harnesses tuned with the latest best practices, and most application builders get better results building on those than reassembling agent loops from parts. It's an 80/20 thing, most use cases are best served by a strong common foundation; the domain-specific cases that need a 10-20% edge may want plugin-level control, and dropping down to something like dsh makes sense there.

And because we sit a layer above, dsh isn't a competitor for us, it's a candidate harness. We can absolutely support it behind the same API and let the market tell us which harnesses win, beyond the launch-week hype. Thanks for the thoughtful question!

   One thing I’d add: this is really composability at two levels. dsh makes the pieces inside one harness swappable. UHP makes the harness itself swappable at the product boundary, while keeping a shared task interface and leaving room for harness-specific extensions.

They’re complementary layers, not competing approaches.

Hi Richard. You mentioned delivery going from weeks to hours once you stopped building your own harness. What was the first thing you shipped that made that obvious?

 Hey Charlie, as a founder/CEO, I constantly need to build a lot of pitch decks and PPTs. I was so frustrated about all AI ppt products in the market and I tried to build one myself. When I first tried it last September, I find it so intimating to even get an agent loop (harness was not a term back then) able to understand a PPT template. A lot of trials and errors, a few weeks and no success. The only learning I had was agent able to generate EChart json config and be embedded into a slide page as an image, following the style.

This year, I retried the same challenge. With the harness being so mature, and a lot of taste skills, I was able to build a fully functional PPT agent within a day. We put our PPT agent implementation as one of our starter kits at

Awesome launch! Taming failure recovery, streaming, and session state across different harnesses into a single protocol is top-tier work. Rooting for you from the agent space!

 Thank you so much for your support, Marcin! I see a huge synergy between the HarnessRouter being an intelligent unit layer, and AgentX's multi-agent orchestration as a mesh layer on top, together we will be form a complete solution for Level 5 of AI: AI Organizations, which is the ultimate step in OpenAI's 5 level AI roadmap

   Thanks Marcin for supporting HarnessRouter team!

Congrats on the launch and kudos to open source! I am wondering how does it work if I want to iterate on the artifacts it returns? And is it possible to iterate with different harnesses? For example if I am not satisfied with the slides codex generated and wanted to use Claude code to refine it, how’d that work?

 Thank you for supporting us! Two different flows here. Iterating itself is the native motion: a session keeps the conversational context and the working directory with all its files, so "make slide 3 less crowded" is just the next turn, the agent edits the same files in the same workspace. In the Slides kit that's literally the design, a deck is one conversation, and slides are real objects on a canvas, so you can also just drag and retype things yourself between turns.

Switching harnesses mid conversation is the interesting one, and the spec takes a deliberate stance: a session is pinned to its harness. Asking Claude Code to continue Codex's session errors loudly (409 harness_mismatch) instead of silently starting over, because continuing a conversation with a different agent IS a different conversation, and doing it quietly loses work you believed you had. The supported flow is: pull the artifacts out (per file or as a zip), start a task on the Claude Code harness with those files as input, and refine from there. Same API shape both ways since file input and artifacts are part of the protocol, so the handoff is a couple of calls, it's just explicit rather than magical. Cross harness refinement is honestly one of the fun workflows: draft with the fast one, polish with the picky one.

   Great discussion! Currently, artifacts are the portable boundary between harnesses, rather than hidden session state. This makes each handoff explicit and reproducible.

the composability answers above cover most of what I'd ask, so a narrower one: Codex, Claude Code and Hermes each have harness-specific stuff that isn't just an implementation detail - things like Claude Code's permission/tool-approval flow or subagent delegation. when a task gets routed to whichever harness actually supports that, does UHP give the calling app a way to detect "this harness can do X" and branch on it, or does building against the common surface mean you're implicitly limited to whatever the weakest supported harness can do

 Thank you for your insightful question! It's the classic abstraction-layer problem, and the trap you're describing (silent LCD) is what UHP is designed against.

First, more normalizes than you'd think. Claude Code's tool-approval flow, from the app's side, is just a lifecycle event: "run paused pending approval, approve/deny." Subagent delegation surfaces as structure in the trace. UHP models these in the common surface (sessions, streaming events, cancellation, structured errors), so harnesses that support them emit them natively.

Second, what doesn't normalize is explicit, not silent: harnesses declare what they support so apps can feature-detect and branch, and invoking an unsupported capability returns a structured error, same pattern LSP used (capability negotiation at init) to avoid LCD across hundreds of language servers.

Third, harness-specific config (permission policies, skills, MCP, model policy) stays typed at the harness-config layer rather than forced through the intersection. So the ceiling is per-harness, not weakest-common.

The common core is what's hardened by the conformance suite today; the capability surface will keep evolving as we add harnesses with weirder shapes. Spec's public and versioned, would honestly love your review on exactly this seam:

 the LSP comparison actually answers it well, that ecosystem survived because capability negotiation was mandatory from day one, not bolted on after servers already shipped assuming a shared baseline. curious if UHP has that same discipline this early, or if the conformance suite is more descriptive right now, catching gaps after a harness adds something new rather than requiring the declaration upfront. will go read the protocol repo, appreciate the detailed answer

 Sharp distinction, Gal! And you're right that it's the thing that decides whether the ecosystem survives.

The declaration is mandatory, at the lowest conformance class. The discovery document at /v1/uhp is required at class Core, capabilities is a required field in its schema, and the semantics are fail closed: a server must report false for what it doesn't implement rather than omitting it, and a client must treat an absent key as false. So there's no path to "conformant" that skips declaring, and no path for a client to assume a shared baseline, because absence reads as no. New capabilities enter as named booleans in an open schema, so a harness with a weirder shape declares first and the spec catches up, rather than the other way around.

Now the candid part, because it's already public in the repo: our own reference implementation initially had no capability discovery at all, and a client had to learn from 404s. Writing the conformance suite caught it, it's listed as defect #1 in the published report, and it got fixed before anything third party shipped against the spec. So you could say we weren't born with the discipline, but we installed it before there was an installed base, which is the window LSP had too.

As for descriptive vs prescriptive: the suite is normative by construction. Passing it is what "conformant" means, every check names the spec section it enforces, and governance requires that no spec change lands unless the spec, the reference implementation, and the suite move together. Our internal phrasing is "a rule nothing tests is a wish." Would love your read on the seam once you've been through the repo!

  that defect #1 admission is the part that actually convinces me, not the spec text itself - a lot of protocols publish nice sounding principles and never say where they broke their own rule first. logging it as defect #1 and fixing it pre-installed-base is the kind of thing you can't fake after the fact. going to go read the conformance suite itself now rather than just the spec doc, curious how many of the checks exist because of a real defect like that one versus being written ahead of any observed failure

Congratulations. And happy product launch.

 Thank you for your support, Huisong! Your support means a lot to us :D

Can a session started with one harness be continued with another, or does switching only happen between tasks?

 Sessions are pinned to their harness by design: continuing a session with a different one fails loudly with a structured error (409 harness_mismatch) rather than silently starting a new conversation, because a session carries conversational context plus a working directory of files, and another harness can't genuinely inherit the first one's conversation state. Switching happens between tasks: download the artifacts (or the whole workspace as a zip), start a task on the other harness with those files as input, and continue from there. Files transfer cleanly; conversation memory intentionally doesn't. We'd rather make the boundary explicit than pretend continuity that isn't real.

Love the idea of treating agent harnesses as infrastructure rather than rebuilding one for every product.

The “OpenRouter for agent harnesses” analogy makes a lot of sense. Codex, Claude Code, Hermes behind one API + a unified protocol could be a really powerful primitive for the next generation of agentic apps.

Excited to see this go beyond coding agents. 🚀

 Thank you Eric! Yes, as we discussed internally at Epsilla, Harness-as-a-Service is the core infrastructure component and fastest way to bring intelligence into application layer. Thinking of a whole computer, harness is the CPU, data/knowledge is the Disk/Memory, horizontal agent platform is the OS, and domain vertical applications are softwares. Being able to leverage HarnessRouter as one of the core components is the competition advantage for Epsilla being an AI-native company.

⁠Curious how you’re handling concurrency. What happens when a lot of users kick off long-running jobs at once? The API feels like the easy part; isolation and recovery are where it usually gets messy.

 Agreed, the API is the easy part. The spec draws one hard line on concurrency: tasks run in parallel across sessions, but never two at once inside the same session. A session is one conversation and one working directory, and two agents writing to both isn't a defined state, so the second request gets a clean structured error instead of a corrupted workspace. For isolation, every session gets its own workspace, state, and checkpoint, with one agent process per session. For recovery, workspaces live on the data volume, so a restart doesn't lose work in flight, and cleaned up idle sessions restore from their checkpoint. And the honest ceiling in the self hosted edition: one box runs what the box can run, concurrency defaults to your core count. Scaling beyond that is what the hosted version exists for.

12
Next