HackerTrans
TopNewTrendsCommentsPastAskShowJobs

clevengermatt

no profile record

Submissions

One interface, every protocol

openbindings.com
57 points·by clevengermatt·3 mesi fa·26 comments

Show HN: OpenBindings – One Contract for REST, gRPC, MCP, GraphQL and Beyond

openbindings.com
1 points·by clevengermatt·3 mesi fa·1 comments

comments

clevengermatt
·3 mesi fa·discuss
Thanks for the clarification. That's a valid implementation strategy for client consumers that want a gRPC feel. The spec doesn't require any particular client pattern (what's on the site is guidance, not normative), so an OBI-conformant toolchain could be built that way. I went with a less prescriptive approach, but that's a preference, not a mandate, and I think it's the right choice specifically for leaving the door open to alternative client implementation patterns like what you're proposing. I appreciate you sticking with this across the thread.

If you're open to it, I'd be interested in staying in touch as OBI evolves. I know you're not sold on the project, but critical voices willing to engage constructively for this long are rare and valuable regardless. If you ever want to poke at something or tell me where you think it's going wrong, I'm at https://x.com/clevengermatt, and there's the GitHub discussions.
clevengermatt
·3 mesi fa·discuss
You're right that what OBI does is structural typing or just interfaces, not duck typing. Transforms and bindings do use the adapter pattern. The critique lands and I can admit it. The duck typing framing was rhetorically appealing but imprecise.

On the gRPC-as-client-layer point, I want to make sure I understand. You're suggesting that between the OBI client SDK and the source service, there should be a gRPC layer, with generated gRPC adapters fronting each source? Or something else?

Worth noting either way: the spec doesn't dictate implementation. It defines operation contracts, binding sources, and the executor role. How an executor actually reaches a service is left open, so gRPC-based routing is a valid strategy within the spec regardless.

Thanks for sticking with this. This is exactly the kind of discussion I was hoping for. I really do appreciate it.
clevengermatt
·3 mesi fa·discuss
Pushing back on the terminology point. Duck typing is defined by how compatibility is determined, not by the absence of declaration. In Swift and Haskell, declaration is what makes a type conform. In Go, structure does, whether you add an optional assertion or not. OBI works the same way. Shapes determine compatibility. Roles and satisfies are optional declarations for explicitness, not a different mechanism.

Duck typing also requires being able to see a duck. Go has methods you can introspect. Raw REST doesn't. OpenAPI and gRPC reflection give you a structural surface, and OBI unifies those into one comparable form above the transport. What you're calling ad-hoc duck typing at the network boundary is humans reading docs and guessing whether the shapes match. That's a weaker version of the same idea, without the mechanical verification that makes duck typing useful. On "just another set of paths and protocols," OBI operation keys are transport-neutral. `tasks.create` has no route baked in. Bindings say how to reach it: REST at POST /tasks, gRPC at TaskService.Create, MCP as a tool. Same operation, multiple bindings, one identifier.

Thanks for the sharpening!
clevengermatt
·3 mesi fa·discuss
[dead]
clevengermatt
·3 mesi fa·discuss
Fair correction. Wire-level copies don't even fully match, and upstream changes can invalidate whatever match exists. That's the weakness of wire-level duck typing. Contract-level compatibility doesn't fully solve the upstream changes problem (nothing does), but when you regenerate the OBI from an updated source spec, a compatibility check tells you structurally what changed. Wire-level clones find out by breaking.

The flip side is worth noting too. If you own the API and want to preserve contract compatibility, OBI lets you change your implementation (paths, payload shapes, even protocols) behind the same contract. Transforms bridge shape differences. Binding swaps change protocols. Consumers targeting the interface don't need to care.
clevengermatt
·3 mesi fa·discuss
Claude writes a lot these days. Sometimes, if it works, I don't change it. Good sense of smell on you.
clevengermatt
·3 mesi fa·discuss
Fair questions.

OBI needs its schema format to be universally parseable, deterministic to compare, and rich enough to describe the portable subset of any binding format's type system. JSON Schema meets those requirements without tying the spec to any one ecosystem. Proto-level fidelity would center gRPC. A custom IDL would fragment tooling. JSON Schema is the neutral ground.

The limitations are real, especially with proto. For example, our own proto interface creator implementation maps 32-bit integers to JSON Schema `integer` and 64-bit integers to `string` to avoid JSON precision loss beyond 2^53, following Proto3's canonical JSON mapping. Proto enums are int-valued with names; JSON Schema enums are typically strings. Proto's oneof differs semantically from JSON Schema's oneOf. Maps with non-string keys can't be expressed directly.

These affect cross-service structural comparison, not execution. Executors handle source types natively on the wire, so int64 stays int64 when you actually make a call. Transforms bridge shape differences between operation schemas and binding sources at runtime. The comparison layer works at a coarser grain in v0.1 because that's what makes it deterministic and universally implementable. Future profile versions can tighten comparison precision as the ecosystem converges on the tradeoffs worth making.
clevengermatt
·3 mesi fa·discuss
[dead]
clevengermatt
·3 mesi fa·discuss
No, and that's the point. You can generate an OBI from AWS's or GCP's existing OpenAPI specs today with the ob CLI. An OBI is a unified primitive that tools can build on. You can generate OBIs ad hoc for your own consumption without the vendor knowing or caring. Vendor buy-in makes the ecosystem stronger, but it's not required to get value.

The longer game is vendor-published OBIs and shared interface roles (e.g. a neutral object-storage interface that S3 and GCS both satisfy), but one OBI, generated from specs that already exist, is still useful on day one.
clevengermatt
·3 mesi fa·discuss
On the web being the duck typing equivalent. That's ad-hoc duck typing at the wire format level. S3-compatible APIs exist because companies reverse-engineered S3's surface and matched it. You have to replicate the paths, headers, and response shapes closely enough that the client libraries can't tell the difference, or they break. There's no spec that declares "I satisfy the S3 interface" and no way for a tool to verify compatibility without running requests.

OBI operates at the contract level instead. Two services with different wire formats can satisfy the same interface as long as their operation shapes match. The binding executors handle the wire differences. That's the duck typing analogy. Match the shape, not the implementation.

You're right that the drivers are partly economic. But technical standards and economics aren't isolated from each other. Terraform, Kubernetes, and OpenAPI itself are technical solutions that enabled economic behavior that wasn't viable before them. Lowering the cost of interop changes what's economically rational to pursue.

On the xkcd, the post addresses this. OBI structurally can't replace OpenAPI, gRPC, or MCP. An OBI without sources and bindings pointing to them is an unbound contract, not an actionable interface. The dependency runs one way. Those specs are inputs, not competitors.
clevengermatt
·3 mesi fa·discuss
The spec isn't hiding JSON Schema. There's a section on it with the dialect URI and the subset of keywords OBI uses: https://openbindings.com/spec#json-schema-dialect

That said, if it feels buried, I'll look at surfacing it more clearly.

You're right about the gRPC fidelity issues though. int64 precision, oneof vs oneOf semantics, enum value mapping, and well-known types all need careful handling when binding to Proto. The tradeoff is that JSON Schema is already the schema format inside OpenAPI, AsyncAPI, and MCP, so OBI can reference their schemas directly without translation. Proto would have given better fidelity for gRPC but required schema translation for every other binding. Picking JSON Schema prioritizes cross-binding reach over depth in any one protocol.

The fidelity limitations deserve clearer documentation. Adding that to the list. Thanks for pushing on this.
clevengermatt
·3 mesi fa·discuss
JSON Schema is already the schema format inside OpenAPI, AsyncAPI, and MCP. Using it means OBI can reference those specs directly without translation. Any other choice would have made interop harder, not easier.

The programming language analogy is about structural compatibility between contracts, not about the wire format the contract is written in.
clevengermatt
·3 mesi fa·discuss
It's made it more tolerable and less visible, but not less real. An LLM can read docs and generate API calls, but it's guessing at structure that could be declared, parsing docs that could be machine-readable, and inferring equivalence that could be verified.

An OBI gives an AI agent typed operations and bindings it can use on the first try. No doc parsing, no guessing at endpoints. And AI can generate OBIs from existing specs or use the ob cli to do it for them.

AI and structured contracts aren't competing concepts. Good interface design matters as much for AI as it does for us. Maybe more.
clevengermatt
·3 mesi fa·discuss
Thanks! Happy to answer any questions if you're interested. The ob demo is the fastest way to see it end to end. Starts a service on six protocols and lets you call it from the CLI.
clevengermatt
·3 mesi fa·discuss
Hi HN. OpenBindings is an open spec for describing what a service does once and binding it to any protocol. You define operations with input/output schemas, then point at your existing OpenAPI doc, proto file, MCP server, or whatever else. The spec doesn't replace any of them. They're inputs.

The short version of why: programming languages have had interfaces and duck typing forever. You code to a shape, not an implementation. The web never got a successful equivalent at the network boundary. OpenBindings is an attempt at that.

What's here today: - The spec (v0.1.0): https://openbindings.com/spec - ob CLI: https://github.com/openbindings/ob - Go SDK: https://github.com/openbindings/openbindings-go - TypeScript SDK: https://github.com/openbindings/openbindings-ts - Binding executors for different protocols

Fastest way to try it: brew install openbindings/tap/ob ob demo

That starts a coffee shop service on six protocols. `ob op exec localhost:8080 getMenu` calls it. The CLI discovers the OBI (OpenBindings Interface) at /.well-known/openbindings and handles the rest.

Would love feedback on the spec design.
clevengermatt
·3 mesi fa·discuss
Hi HN. OpenBindings is an open spec for describing what a service does once and binding it to any protocol. You define operations with input/output schemas, then point at your existing OpenAPI doc, proto file, MCP server, or whatever else. The spec doesn't replace any of them. They're inputs.

The short version of why: programming languages have had interfaces and duck typing forever. You code to a shape, not an implementation. The web never got a successful equivalent at the network boundary. OpenBindings is an attempt at that.

What's here today: - The spec (v0.1.0): https://openbindings.com/spec - ob CLI: https://github.com/openbindings/ob - Go SDK: https://github.com/openbindings/openbindings-go - TypeScript SDK: https://github.com/openbindings/openbindings-ts - Binding executors for different protocols

Fastest way to try it: brew install openbindings/tap/ob ob demo

That starts a coffee shop service on six protocols. `ob op exec localhost:8080 getMenu` calls it. The CLI discovers the OBI (OpenBindings Interface) at /.well-known/openbindings and handles the rest.

Full writeup on how I got here: https://openbindings.com/blog/one-interface-every-protocol

Would love feedback on the spec design.