Languages Become Interfaces
Most language interoperability starts at the wrong layer.
It starts with calls.
Can JavaScript call Rust? Can Swift call C? Can Python call a TypeScript service? Can WebAssembly sit between them?
Those are useful questions, but they are not the deepest question.
The deeper question is:
what does each side believe the program means?If two languages only share a call boundary, they can exchange bytes, handles, objects, or messages. That is not the same as sharing state identity, type shape, permissions, effects, ownership, runtime assumptions, or proof.
The stronger form of interoperability is semantic.
- Shared contract
- identity, state, actions, effects, typesLanguages meet through stable meaning, not through one target syntax.
- Native implementations
- Rust, TypeScript, Swift, Python, HTML, CSSEach language keeps its idioms while binding to the same contract.
- Interop evidence
- source spans, adapters, gates, runtime proofA boundary is trusted only to the degree that it can explain what survived.
- Known loss
- weaker types, missing ownership, runtime-only checksInteroperability should record loss instead of hiding it behind a successful build.
Not One Language
The goal is not to replace every language with one universal syntax.
That would miss why languages exist.
Rust is good at making ownership and lifetimes explicit. TypeScript is good at expressing structural API shape in a JavaScript ecosystem. SwiftUI is good at native UI declaration. CSS is its own runtime for cascade and layout. SQL expresses relational constraints. Python is often the fastest way to bind data tools and operational scripts.
The point is not to flatten those differences.
The point is to let those differences attach to one semantic boundary.
Rust keeps ownership.
TypeScript keeps structural API shape.
SwiftUI keeps native view idioms.
CSS keeps cascade semantics.
Python keeps orchestration ergonomics.
The shared layer keeps identity, contracts, effects, proof, and loss.That is a different promise than source-to-source translation.
Translation says:
turn this language into that languageInteroperability says:
let these languages cooperate without lying about what each one can expressThe Contract Is The Meeting Point
Imagine a search capability.
One part is implemented in Rust because the index needs speed and ownership discipline. Another part is exposed in TypeScript because the product shell is web-based. A native client wants SwiftUI. An automation system wants a command interface. A dashboard wants HTML, CSS, and runtime probes.
The old shape is a pile of adapters:
Rust library -> Node binding -> TypeScript wrapper -> API route -> Swift client -> dashboard widgetEvery edge has a private agreement.
The semantic shape is different:
capability SearchIndex @id("cap_search_index") {
capability search.query
input SearchQuery
returns SearchResults
effects cpu.read, storage.read
resources SearchCorpus.documents
}
action runSearch @id("action_run_search") {
input SearchQuery
returns SearchResults
reads SearchCorpus.documents
uses search.query
}Now each language is not integrating with every other language directly.
Each language is integrating with the contract.
1capability SearchIndex @id("cap_search_index") {2 capability search.query3 input SearchQuery4 returns SearchResults5 effects cpu.read, storage.read6 resources SearchCorpus.documents7}8 9action runSearch @id("action_run_search") {10 input SearchQuery11 returns SearchResults12 reads SearchCorpus.documents13 uses search.query14}The ABI Moves Up
An ABI normally describes how compiled code talks at the machine boundary.
Calling convention. Memory layout. Symbol names. Registers. Stack shape.
That still matters.
But for malleable software and agent-built systems, the more important ABI moves up:
this is the stable identity
this is the data shape
this is the ownership rule
this is the effect boundary
this is the runtime assumption
this is the proof required before useThat higher-level ABI is what lets software be composed across languages without turning every boundary into bespoke glue.
Interoperability Is Not Equivalence
This is the part that has to stay honest.
Two projections can be interoperable without being equivalent in every local detail.
A Rust implementation may prove ownership statically. A JavaScript caller may only preserve the call contract and rely on runtime checks. A SwiftUI surface may preserve the action and data shape but add UI lifecycle behavior. A CSS projection may preserve selectors and tokens while leaving layout proof to a browser probe.
The system should not pretend those are the same.
It should say:
same identity
compatible data shape
different enforcement mechanism
adapter required
runtime proof required
loss recordedThat honesty is what makes the system useful.
- Name matchweakCan proveThe target has a symbol that claims to implement the contract.Stops atDoes not prove shape, authority, or behavior.Bind candidate
- Shape matchpartialCan proveInputs, outputs, and public declarations line up.Stops atDoes not prove effects or runtime behavior.Run compatibility gate
- Capability matchboundedCan proveThe target only reads, writes, and effects what the contract allows.Stops atDoes not prove target runtime conditions.Admit authority
- Runtime probeobservedCan proveThe projected boundary is exercised under declared conditions.Stops atOnly covers the probed states and environments.Admit behavior
- Loss accountstrongCan proveAnything not preserved is explicit enough to route, review, adapt, or refuse.Stops atDoes not make the lost feature safe by itself.Decide boundary
Routing Instead Of Glue
Once language boundaries become semantic, the system gets a better set of choices.
It does not only compile or fail.
It routes.
What Changes
This makes languages feel less like sealed worlds.
Not because their syntax disappears.
Because their useful meanings become addressable.
A Rust module can provide a capability to a TypeScript shell. A SwiftUI view can mount over a contract authored somewhere else. A Python worker can consume the same action surface as a browser UI. A CSS layer can bind to design tokens whose identity survives a projection. A plugin can be written as a semantic contract and lowered into several hosts.
The important move is that the boundary stops being:
language A calls language Band becomes:
language A and language B both attach to contract CThat is why semantic merging and language translation are the same project.
If the system can prove what changed, it can merge. If it can prove what survived, it can project. If it can prove what a boundary means, languages can interoperate without collapsing into one language.
The future is not one perfect programming language.
It is many languages connected by contracts that can be inspected, lowered, tested, merged, and refused.