Blog

From API-Led to Capability-Led Connectivity

Jerome Louvel ·October 21, 2026
Table of contents

API-led connectivity gave integration a shared vocabulary: System APIs unlock systems of record, Process APIs orchestrate them, and Experience APIs shape the result for each consumer. A decade later, it’s still how most integration teams think.

Its best practitioners have also been honest about its cost. In 5 integration patterns to debunk the myths about API-led connectivity, a MuleSoft architect, Hemalatha Bahadur, names three myths: all three layers are mandatory, every layer needs an API for security, and every layer needs an API for agility. She then shows five patterns, from three layers down to a single System API. Her reason is simple: every layer is another API to build, deploy, run and keep within its SLA.

That’s the right lesson. Agents change what it costs to follow it. Capability-led connectivity keeps API-led’s layers and its ownership model, but stops paying a deployment for each one.

In API-led, a layer is a deployment

Each API-led layer is a running API with its own runtime, its own policies and its own network hop. That’s why “how many layers?” is a real architectural decision. Add a layer and you get reuse and isolation, but also cost, latency and another thing to operate. Skip one and the next consumer may force you to add it later.

The article’s five patterns are what that trade-off looks like in practice:

Pattern Layers When
Three layers System → Process → Experience Systems have no API, the logic needs orchestration, several consumers
“Buddy” System layers Vendor API → System → Process → Experience The vendor exposes an API, but you need to enrich it and apply policies
No Experience layer Vendor API → System → Process The Process API already fits its one consumer
System and Process only System → Process Same, but the systems have no API
System only System A file transfer with no business logic

In a capability, a layer is a section of one file

An Ikanos capability declares the same three concerns in one YAML spec: consumes for the systems it calls, aggregates for the flows that orchestrate them, and exposes for the surfaces it offers. One engine runs it, and the spec is the runtime contract.

This changes the economics. Leaving a layer out means leaving a section out. Adding one later doesn’t add a deployment, a network hop or a separate SLA. The question “how many layers can we afford?” becomes “what shape does this use case need?”

Here are two of the article’s patterns in one spec: a shaped passthrough (System only) and an orchestrated flow (all three layers), projected to MCP, REST and an Agent Skill.

capability:
  consumes:                      # System
    - type: "http"
      namespace: "erp"
      baseUri: "https://erp.internal.example/api"
      authentication:
        type: "bearer"
        token: "{{secrets.ERP_TOKEN}}"
      resources:
        purchase-order:
          path: "/purchase-orders/{{po-id}}"
          operations:
            get-purchase-order:
              method: "GET"
        shipments:
          path: "/purchase-orders/{{po-id}}/shipments"
          operations:
            list-shipments:
              method: "GET"

  aggregates:                    # Process, defined once
    - namespace: "po-tracking"
      flows:
        track-purchase-order:
          description: "Purchase order status with its latest shipment."
          semantics: { safe: true, idempotent: true }
          steps:
            po:   { type: "call", call: "erp.get-purchase-order" }
            ship: { type: "call", call: "erp.list-shipments" }
          mappings:
            - { target: "status",          value: "$.po.status" }
            - { target: "latest-shipment", value: "$.ship[0].status" }

  exposes:                       # Experience, one per audience
    - type: "mcp"
      namespace: "po-mcp"
      tools:
        track-purchase-order:    # three layers
          ref: "po-tracking.track-purchase-order"
        get-purchase-order:      # System only, but shaped
          call: "erp.get-purchase-order"
          outputParameters:
            - type: "object"
              properties:
                status:   { type: "string", mapping: "$.status" }
                supplier: { type: "string", mapping: "$.supplier.name" }
    - type: "rest"
      namespace: "po-api"
      resources:
        tracking:
          path: "/purchase-orders/{{po-id}}/tracking"
          operations:
            track: { method: "GET", ref: "po-tracking.track-purchase-order" }
    - type: "skill"
      namespace: "po-skills"
      skills:
        purchase-orders:
          tools:
            track-purchase-order:
              from: { sourceNamespace: "po-mcp", action: "track-purchase-order" }

Abridged for reading: ports, parameter declarations, descriptions and the binds block are omitted. The full version validates against the Ikanos JSON Schema and passes the shipped Polychro ruleset with no findings.

Flows compose too

This answers the question that started Bahadur’s article, “is it possible to have more than one System API layer?”, and generalizes it. In API-led, a Process API that builds on another Process API is one more deployment and one more network hop. In Ikanos, a flow can call another flow with the same type: call step it uses for an upstream operation:

supplier-po-summary:
  semantics: { safe: true, idempotent: true }
  steps:
    tracking: { type: "call", call: "po-tracking.track-purchase-order" }   # another flow
    po:       { type: "call", call: "erp.get-purchase-order" }             # an upstream API
  mappings:
    - { target: "status",   value: "$.tracking.status" }
    - { target: "supplier", value: "$.po.supplier.name" }

So the Process layer isn’t one layer at all. It’s as many levels as the domain needs, all inside the same engine with no extra hop. Two linter rules keep that graph honest: flows can’t call each other in a cycle, and a flow that claims to be safe or idempotent can’t call one that isn’t. Both are checked again by the engine at startup.

Why agents care more than apps

The article’s third cost is the one that matters most here: myths that end up “giving the consumer inaccurate or more elements than what they should consume.” For a web app, extra fields are a nuisance. For an agent, every surplus field and every surplus tool uses context, adds tokens and makes the wrong call more likely.

That changes how the patterns apply:

  • “Skip the Experience layer” rarely survives an agent. An agent always needs a tool description, typed inputs, behavior hints and a trimmed result. But in a capability, that shaping is an exposes entry, not another API.
  • “System only” holds, if the output is shaped. A one-to-one passthrough is fine. Mirroring a raw API into an agent isn’t. A call: with explicit outputParameters is the System-only pattern done right: only the mapped fields leave the engine.
  • Per-consumer Experience APIs get cheap. A new audience is a new exposes entry pointing at the same flow, which is why the spec above serves an agent, a vendor portal and a skill without duplicating logic.
  • The “buddy” System layer now includes MCP. The vendor API you wrap no longer has to be REST or SOAP. With 1.0.0-beta8, releasing next week, a capability can consume an upstream MCP server (consumes: type: mcp, over Streamable HTTP), including another team’s or a vendor’s published capability. It composes that server’s tools in a flow with typed inputs and outputs and locally declared behavior hints.

Three owners, one runtime contract

The strongest objection from an API-led architect isn’t technical. It’s about ownership. As Alex Lima puts it in MuleSoft Integration Patterns — API-Led Connectivity, System APIs belong to central IT and change every 6–12 months, while Experience APIs belong to app teams and change every few weeks. So who approves a pull request on a file that holds both?

Nobody has to. Each section of an Ikanos spec can live in its own file and be imported where it’s used. The schema accepts documents that contain only consumes, only aggregates or only exposes. Central IT owns shared/erp-consumes.yml, a domain team owns the flows, and the agent team owns the exposes block. Code owners map onto files the way they always have.

The file boundary follows the team boundary. The deployment boundary doesn’t have to.

Coding agents write the layers too

There’s another reason layers get cheap: AI coding agents are very good at writing Ikanos YAML. A capability is a small, fixed vocabulary (consumes, aggregates, exposes, binds) constrained by one JSON Schema. There’s no framework to learn, no general-purpose code to get subtly wrong and no build step. Models produce structured YAML reliably when a schema bounds it, and this format was designed with that in mind.

In practice, adding a layer is a prompt, not a project:

  • Start from what you have. ikanos import openapi turns an existing Swagger or OpenAPI contract into a starting consumes block, so the agent curates and composes instead of writing from scratch.
  • Give the agent the rules. An ikanos-capability agent skill teaches Copilot, Claude Code, Cursor and other coding agents how to author, validate and debug capabilities.
  • Let it check its own work. Polychro runs as an MCP server, so the agent can generate, lint and fix in the same turn, before anything reaches a pull request.
  • Review one diff. The change is a few lines in one readable file. What the agent wrote is exactly what will run, because the spec is the runtime contract.

Compare that with asking an agent to add an API-led layer: a new project, flow configuration, transformation scripts, deployment descriptors and gateway policies, across several artifacts that each need their own review. The more of the integration lives in one bounded spec, the more of it an agent can write safely.

Governance moves into the spec

Nitin Surana’s Event-Driven Architecture and API-Led Connectivity, on MuleSoft’s own blog, calls governance “the Achilles’ heel for both API-led connectivity and EDA”: usually manual where it exists at all. Lima lists it as pitfall number one.

When the integration is the spec, governance can check the whole integration, not just its API contract. Polychro runs the same ruleset in the editor, in the coding agent’s turn and in CI as a GitHub Action. The shipped Ikanos ruleset checks things a contract-only linter can’t see, for example:

  • ikanos-flow-call-semantics-conservative: a flow that claims to be safe or idempotent can’t call operations that aren’t.
  • ikanos-flow-call-no-cycle: flows that call other flows must form an acyclic graph.
  • ikanos-exposes-call-not-flow: exposed tools reach flows through ref:, so they inherit the flow’s description, hints and schemas instead of bypassing them.

Every upstream operation a credential can reach is written in the spec, so a reviewer can list them all before the credential is bound.

What a capability doesn’t replace

The same sources are clear that request–response isn’t the whole of integration, and that’s worth saying plainly.

  • Events and streams. Surana’s case for event-driven architecture covers keeping data fresh without polling, absorbing bursts by acknowledging now and processing later, and streaming. Ikanos is request–response today. A webhook adapter and long-running MCP Tasks are designed but not shipped. Streaming is out of scope.
  • Steps run in sequence. A flow with three upstream calls pays roughly the sum of their latencies. Parallel steps are planned for Q4, which brings that down to roughly the slowest call.
  • Connector breadth, messaging and B2B. An iPaaS estate brings a large connector catalog, reliable messaging and EDI partner management. A capability is often best deployed alongside that estate, as the agent-facing layer over APIs you already run.

Layers were the right idea. What agents change is the price of each one, and the question you ask before adding it.

The takeaway

  • API-led’s own practitioners say three layers is a starting point. Each layer costs a deployment, so choosing how many is the real skill.
  • In a capability spec, a layer is a section of one file. Choosing a pattern becomes a choice of shape, not of infrastructure.
  • Agents punish oversized payloads hardest, so shape every exposed tool, even a passthrough.
  • Keep the ownership model: split sections into team-owned files and import them.
  • A schema-bounded spec is what coding agents write best, so the next layer is a reviewed diff, not a project.
  • Let the linter check the whole integration, because in a spec the integration is the contract.

Further reading

Subscribe to the Naftiko Manifest

Want to learn more and stay up to date on the latest from Naftiko? Get new posts, releases, and signals from the capability fleet in your inbox.