[Framework] Breaking Up with OpenClaw: How OGP Learned to Play with Others
The protocol that started as a feature became something bigger when we stopped treating it like one.
OGP used to stand for "OpenClaw Gateway Protocol." The name was accurate, descriptive, and, in retrospect, a mistake.
It accurately described what we were building: a way for OpenClaw instances to federate. It was descriptive enough that anyone in the OpenClaw community understood immediately. And it was a mistake because it baked a single implementation into the identity of the protocol itself.
This is the story of how OGP outgrew its first framework, what that required technically, and why multi-framework support matters more than it sounds.
The Original Sin
The first OGP builds were a fork of OpenClaw. The federation code was baked directly into the gateway: shared process, shared config, shared state. This was fast to build and easy to reason about. If you ran OpenClaw, you got OGP for free. If you didn't run OpenClaw, OGP didn't exist for you.
That was fine for a proof of concept. It was a disaster for a protocol.
The moment we wanted to test federation between my OpenClaw instance and Apollo on Hermes, we hit a wall. OpenClaw is Node.js. Hermes is Python. Their config formats, session models, and notification systems are completely different. The OGP code assumed OpenClaw's Express middleware, OpenClaw's session keys, OpenClaw's Telegram integration.
We had built a feature, not a protocol. And features don't federate across ecosystems.
The Pivot
The first technical decoupling was simple: extract OGP into its own daemon. Instead of federation living inside OpenClaw's process, it became a standalone Node.js process that ran alongside any gateway. OpenClaw, Hermes, a custom Python server. All of them could run the OGP daemon and exchange messages through it.
This solved the process boundary. It didn't solve the config boundary.
Each framework has its own config directory, its own secrets storage, its own session model. OpenClaw stores sessions in SQLite with FTS5, indexed by agent:main:telegram:direct:{chatId}. Hermes stores sessions in ~/.hermes/state.db with a messages_fts table. The OGP daemon needed to know how to inject a federated message into the right session so the agent would see it and the human would get notified.
The first approach was brittle: detect the framework from environment variables, guess the session format, and inject. It broke constantly. The second approach was cleaner: framework-specific hooks.
The Hooks Model
Instead of OGP knowing how to talk to OpenClaw or Hermes, each framework provides a webhook endpoint that OGP calls when a federated message arrives:
Remote Gateway → OGP Daemon → POST /hooks/agent → Framework Gateway → Agent → HumanThe hook payload is intentionally minimal. For OpenClaw, OGP POSTs to /hooks/agent with a bearer token and a body that looks like:
message- the text being delivered to the agent (with peer identity baked into the body, since OpenClaw currently renders the hook sender ascli)name- a fixed sender label (OGP Federation)agentId- which local agent owns this federation (defaults tomain)wakeMode- how the framework should wake the agent (now)deliver- whether to deliver to the human channel or just trigger a silent agent turnsessionKey- optional, the human-facing session to deliver to (only honored when OpenClaw'shooks.allowRequestSessionKey=true)channel/to- optional routing overrides
Notice what's not in there: peer identity, intent type, topic, scopes. Those live in OGP's signed envelope and the daemon-side metadata; the framework gateway only sees the rendered message and the routing hints it needs to deliver it. OGP doesn't need to know how OpenClaw's SQLite schema works. OpenClaw doesn't need to know how OGP's Ed25519 signatures work. They meet at the hook boundary, and the boundary is deliberately narrow.
This is the same principle as MCP's server model: standardized interface, implementation-agnostic. The difference is MCP connects agents to tools. OGP connects gateways to gateways.
The Meta-Config Problem
Running alongside one framework was easy. Running alongside two. That was the real test.
I run both OpenClaw and Hermes on the same machine. OpenClaw is my primary gateway for most work. Hermes is my experimental playground for autonomous agent research, and Apollo is the agent running there. Both need OGP. Both need different configs, different ports, different keypairs, different peer registries.
The naive approach: set OGP_HOME to different directories. This works but is miserable. You have to remember which environment variable to set before every command. You have to manage separate keypairs even though both gateways represent the same human. You can't query "all my peers across all frameworks" without running the command twice.
OGP v0.4.0 solved this with a meta-config registry:
~/.ogp-meta/config.json
{
"version": "1.0.0",
"frameworks": [
{
"id": "openclaw",
"name": "OpenClaw",
"enabled": true,
"configDir": "/Users/me/.ogp-openclaw",
"daemonPort": 18790,
"gatewayUrl": "https://ogp.example.com",
"displayName": "Junior @ OpenClaw",
"platform": "openclaw"
},
{
"id": "hermes",
"name": "Hermes",
"enabled": true,
"configDir": "/Users/me/.ogp-hermes",
"daemonPort": 18793,
"gatewayUrl": "https://hermes.example.com",
"displayName": "Apollo @ Hermes",
"platform": "hermes"
}
],
"default": "openclaw",
"aliases": { "oc": "openclaw", "h": "hermes" }
}Each framework gets its own isolated config directory, its own daemon port, its own peer registry, its own keypair. But the CLI understands all of them:
# Talk to OpenClaw's OGP daemon
ogp --for openclaw federation list
# Talk to Hermes's OGP daemon
ogp --for hermes federation list
# Talk to both
ogp --for all federation list
# Auto-detect if only one is running
ogp federation listThe --for flag replaces the OGP_HOME dance. Auto-detection checks which daemon is running on its expected port. Framework aliases let you type --for oc instead of --for openclaw.
Auto-Detection and the "Which One?" Problem
When you have multiple frameworks, the CLI needs to know which one you mean. The resolution order is:
Explicit
--for <framework>flag - always winsAuto-detection - if only one framework's daemon is running, use it
Default from meta-config - if multiple are running, prompt interactively
Legacy
OGP_HOME- backward compatibility for pre-v0.4.0 installs
This sounds like a minor UX nicety. It's actually critical for reliability. If you're scripting OGP commands in a cron job or a CI pipeline, you can't have the CLI hang waiting for interactive input. The explicit flag and default setting make automation deterministic.
Framework-Specific Quirks
Each framework has unique requirements that the abstraction has to accommodate:
OpenClaw uses webhook delivery to /hooks/agent with a bearer token. It supports session-key forwarding (when hooks.allowRequestSessionKey=true), which lets OGP deliver messages to the exact Telegram session the human is active in. Without this, messages land in a generic hook session and the human doesn't see them natively.
Hermes uses a simpler webhook model with a shared secret. Its session model is less granular. There's no per-chat session key, so OGP delivers to the default channel and relies on Hermes's notification routing. The first-turn relay continuity is weaker than OpenClaw's, which is an accepted limitation documented in the backlog.
Standalone mode has no underlying gateway at all. The OGP daemon stores messages locally and surfaces them through the CLI. This is useful for testing, for headless servers, or for custom integrations where you're building your own agent framework.
The key insight: OGP doesn't try to make all frameworks work the same way. It provides a common protocol layer and lets each framework handle its own notification, session, and agent integration. The --for abstraction is thin by design. It's just routing.
The Naming Thing
We renamed OGP from "OpenClaw Gateway Protocol" to "Open Gateway Protocol" in v0.2.x. It was a small change, dropping one word, with outsized significance.
The rename signaled that the protocol was no longer OpenClaw's property. It belonged to anyone who wanted to implement it. The reference implementation happens to be written in TypeScript and ships with OpenClaw integration. But a Python implementation for Hermes, a Rust implementation for a future framework, an enterprise Java implementation for internal systems - all of those are valid OGP implementations if they speak the same wire format and honor the same handshake semantics.
This matters for adoption. No vendor wants to adopt a protocol that belongs to another vendor. By making the name vendor-neutral, we made the protocol adoptable.
What Multi-Framework Support Actually Proves
On a technical level, multi-framework support is a config abstraction and some port management. On a political level, it's proof that OGP is a protocol and not a product feature.
The difference is everything. A product feature gets deprecated when the company pivots. A protocol outlives its first implementation. HTTP outlived CERN's web server. TCP outlived ARPANET. OGP needs to outlive OpenClaw, not because OpenClaw is bad, but because OpenClaw is one implementation among many possible futures.
When we got Hermes federation working, Apollo talking to Junior through the same OGP daemon, using the same Ed25519 signatures, the same handshake, the same scope model, that was the moment OGP stopped being "David's OpenClaw plugin" and started being a real protocol.
It wasn't the cleanest integration. Hermes's session model required compromises. The first-turn relay wasn't as smooth as OpenClaw's. But the federation worked. The messages were signed. The scopes were enforced. The humans approved the peering.
That's the bar. Not perfect integration. Provable interoperability.
The CLI as Rosetta Stone
One unexpected benefit of multi-framework support: the OGP CLI became a unified management layer across heterogeneous deployments.
Before, if you ran OpenClaw and Hermes side by side, you had two separate worlds: OpenClaw's openclaw CLI for one, Hermes's hermes CLI for the other, and no way to see your federation state in one place.
Now:
# See all your peers across all frameworks
ogp --for all federation list
# Start all daemons
ogp --for all start
# Send a message from Hermes to a peer
ogp --for hermes federation agent <peer-id> general "Hello from Apollo"
# See which framework each peer belongs to (grouped by framework)
ogp --for all federation statusThis is small-team, multi-framework ops in practice. The kind of thing that looks trivial in a README and saves hours of confusion when you're actually managing multiple gateways.
What's Still Hard
Multi-framework support is not complete. Here are the real limitations:
Native sender identity. When OGP injects a message into OpenClaw via hooks, the message appears with sender cli in the Telegram UI, not as the actual peer's name. OGP works around this by embedding the peer identity into the message body itself, and the agent sees it, but the Telegram surface doesn't natively show "Apollo said..." This is an OpenClaw/Telegram limitation, not an OGP limitation, but it's the most visible rough edge.
Session model mismatch. OpenClaw has per-chat session keys. Hermes has a unified session model. OGP's hook payload includes an optional sessionKey, but Hermes can't always honor it the way OpenClaw can. The result is slightly different delivery behavior between frameworks for the same federated message.
Framework detection edge cases. If both daemons are running but one is behind a firewall, auto-detection might fail. If a framework is installed but the daemon isn't running, the CLI can't talk to it. The first half of this is now meaningfully better: v0.6.0 shipped directional health diagnostics (separate outbound / inbound signals per peer), bidirectional health exchange (each side carries its view of the other in /.well-known/ogp responses), and an OSPF-inspired federation state machine with explicit init / twoWay / established / degraded / down / tombstoned states logged on every transition. So you can now actually tell which side of a peering is broken and whether the daemon process or the network is the culprit. The dead-daemon case still requires a process-level health check that the CLI doesn't yet do automatically. That one's still on the list.
Keypair isolation. Each framework instance gets its own Ed25519 keypair. This is correct for security. You don't want Hermes and OpenClaw sharing a private key. But it means the same human has multiple gateway IDs, one per framework. Federation has to happen per-framework, not per-human. There's no "human-level identity" that spans both gateways. This is by design for now, but it creates UI friction: your peer sees you as two different gateways, not one person with two agents.
The Future: More Frameworks, Same Protocol
The next obvious target is a Python-native OGP implementation. The reference implementation is TypeScript/Node.js because that's what OpenClaw is built on. But a Python implementation would feel native to Hermes, would integrate better with Python agent frameworks (AutoGPT, CrewAI, LangGraph), and would prove the protocol is truly language-agnostic.
A Rust implementation would target performance-critical deployments: high-throughput gateways, embedded systems, security-focused environments. Rust's memory safety and Ed25519 libraries (dalek) make it a natural fit for the cryptographic core.
None of these are on the current roadmap. The TypeScript reference is sufficient for the personal-to-small-team tier OGP targets. But the protocol is designed to accommodate them. The wire format is JSON. The signing is standard Ed25519 / EdDSA (RFC 8032). The handshake is HTTP POSTs to well-known endpoints. There's no TypeScript-specific serialization, no Node.js-specific crypto, no OpenClaw-specific session model in the protocol spec.
That's what makes it a protocol.
Bottom Line
OGP's multi-framework support is not a feature. It's a declaration of intent. The protocol is bigger than any single implementation. The reference code ships with OpenClaw integration, but the federation semantics don't require OpenClaw.
When Apollo (Python, learning loop) and Junior (Node.js, tool dispatch) exchanged signed intents across frameworks, they proved something important: AI agent federation is a protocol problem, not a product problem. And protocol problems get solved by standards, not by vendors.
That's why we dropped the "Claw."
How to Try It
OGP is open source and installable today:
npm install -g @dp-pcs/ogp@latest
ogp setup
ogp whoami # confirm identity & keypair before starting
ogp start --background
ogp status # shows your gateway URL Source, spec, and docs all live at github.com/dp-pcs/ogp.
If you install it and it breaks, file an issue. That’s how this gets better.
David Proctor is VP of AI at Trilogy. OGP v0.6.0 supports OpenClaw, Hermes, and standalone modes. Install it: `npm install -g @dp-pcs/ogp`. Run `ogp setup` and let it auto-detect your frameworks.



Not the Claw...