Apps that ask for results, not endpoints: a runtime capability graph
ArchitectureDevelopmentFundamentalsAI & LLMs
Decoupling apps, mobile apps especially, from the APIs behind them. The cloud publishes a machine-readable map of what it can do; the app asks for a result, such as a user's avatar; a small planner inside the app finds the best way to get it, falls back when a step fails, and learns from every client which paths actually work. AI is optional: the deterministic system works without it.
The app shouldn't know the backend's shape
Today an app is tied to URLs, endpoint names, API versions and the exact order of calls, so the cloud can't reorganize its services without shipping a new app release. This moves that knowledge into a map the cloud publishes and a planner the app runs: the app depends on stable capabilities and typed data, and the backend is free to change underneath.
Goals instead of calls
The app says what it needs, down to the field.
Instead of calling a login endpoint, then a user endpoint, then a profile endpoint, the app asks for a goal: the dashboard needs the user's display name, avatar, notifications and reports. Asking for fields rather than whole objects lets every layer skip work nobody asked for, the way a database skips columns a query doesn't select.
Each service publishes a contract of what it can produce: operations, inputs, outputs, fields, dependencies, authentication and authorization requirements, versions, and hints about cost and latency. The platform merges them into a registry, and every client receives an effective manifest: only what it is allowed and able to use, after health, subscription, permissions, region and rollout are applied.
- Goals with field-level selection
- Service contracts: inputs, outputs, dependencies, auth, versions, cost
- Capability registry of what is deployed
- Effective manifest per client, filtered by policy
Example: the map builds itself in a Kubernetes cluster
Every service brings its own piece of the map.
Each service in the cluster ships its contract next to its code: what it produces, what it needs, its versions and its cost hints. A map builder in the cluster watches deployments; when a service is deployed, scaled to zero or removed, it collects the contracts of the services that are actually running and merges them into one versioned map.
Nobody edits the map by hand. Deploying a new version of the profile service that also produces the avatar adds a new path to the map automatically, and retiring an old service removes its paths, so the map always describes what is really running.
service contracts→map builder (watches the cluster)→versioned capability map
- Contracts shipped with each service
- Map builder watching deployments
- Merged into one versioned map
- No hand-edited configuration
Example: the same map, filtered per client
Conditions decide which part of the map each client sees.
The full map is never sent as it is. Before a client receives it, it is filtered by conditions: service health, the client's subscription and permissions, its organization and region, the current rollout or experiment, and what the app version supports.
Two users opening the same screen can get different maps: a user on the free plan doesn't see the report export at all, a user in another region gets the provider closest to them, and while the notification service is degraded, every client's map points to the older version that still works. The app needs no version checks of its own: if a capability isn't in its map, the feature is simply hidden.
- Filtered by health, subscription and permissions
- Region and organization rules
- Rollout and experiment groups
- Features hidden when their capability isn't in the map
Example: a new map without a hiccup
The slow work happens in the background, on the old map.
When the cloud publishes a new map, the app downloads it in the background and keeps running on the plans it already trusts from the current one. Nothing the user is doing waits for the new map.
When the app is idle, it plans its usual goals again on the new map, compares the new routes with the ones it has, and tries them where that is safe. Only then does it switch: plans that are still valid are kept, better ones are promoted, and the old route stays as a fallback. The user never sees a pause while the app recomputes its paths.
map v1 in use→map v2 downloaded→re-plan while idle→compare and test→switch, v1 kept as fallback
- New map downloaded in the background
- Current plans keep running meanwhile
- Re-planning while the app is idle
- Switch only when the new plans are ready
- Old routes kept as fallback
One goal, several paths
The best path isn't always the shortest one.
A user's avatar might come from the user service, from the profile service, or straight from a CDN. The planner scores each path on latency, bytes, number of hops, cost, reliability and past success, and the weights depend on the moment: on a home network a larger payload is cheap; on a weak mobile connection fewer bytes and fewer round trips win; offline, only the local cache counts.
It works like a database query optimizer spread across services: the app's planner chooses the route, the cloud's planner decides how a capability is produced, and each service skips joins and data sources the requested fields don't need.
Goal→planner→path A · path B · path C→scored for this network→best plan
- Paths scored on latency, bytes, hops, cost, reliability, history
- Network-aware: LAN, Wi-Fi, weak mobile, offline
- Planning at app, cloud and service level
- Unneeded fields and joins skipped
Plans that fail gracefully and survive updates
A plan is a stored object: the goal, its steps, where it is now and what happened so far. If A → B → C fails at B, the planner looks for another way from A to C instead of starting over; if a later step fails, it continues from the last step that worked.
Successful plans are cached, and each plan records only the capabilities it depends on. A new map that changes payments doesn't invalidate a plan that only fetches avatars, so plans stay valid across map versions. Providers that keep failing are marked degraded or open, like a circuit breaker, so a broken route isn't picked again and again.
- Resumable plans: reroute from the last good step
- Plan cache keyed on the capabilities it uses
- Valid across map versions when its dependencies don't change
- Circuit breaking per provider, with known-good and known-bad paths
Every client is a sensor
The cloud learns which paths actually work.
Clients report each plan they ran: the path, the version tried, the result, the fallback used, the latency and the network they were on. The cloud aggregates millions of these and sees what server metrics miss: an HTTP 200 the app can't parse, a failure only in one region or on one kind of device.
Paths move from discovered to tested, proven and preferred; a better path is promoted while the old one stays as a fallback. New API versions roll out gradually, 5% of clients, then 20%, then all, with the clients' reports deciding each step. When a new map arrives, clients keep their known-good plans and look for better ones in the background, when the app is idle.
- Client telemetry per plan and step
- Paths promoted from discovered to preferred
- Gradual version rollouts decided by real results
- Background re-planning when the app is idle
AI proposes, the graph decides
When the planner can't find a route, a local model, or a larger one in the cloud, can propose one. A proposal is never trusted directly: it is checked against the graph, the types, the permissions and policy, tested, and only then promoted into the deterministic graph that every client receives. AI improves the system instead of becoming a dependency of every request, and its answers are cached so thousands of clients don't ask the same question.
If many clients ask for something no path can produce, that is not just a client error: it is demand for a capability that doesn't exist yet, and it shows up as a signal for the team to build it.
- Deterministic planning first, AI only when stuck
- AI proposals validated against graph, types and policy
- Validated routes become part of the graph
- Unmet goals reported as missing capabilities
What else it gives
Because the graph knows dependencies and alternatives, it can generate tests for every path, fallback, permission and version. The same manifest can switch features in the app on and off without hard-coded version checks. And the same planner can serve a mobile app, a desktop app, a command-line tool or an AI agent, so people, apps and agents share one meaning of the API.
- Stack
- Capability contracts · Graph planning · Telemetry

