Skip to content
pacto

Service contracts

Know which services a change breaks before it ships.

One YAML contract per service. pacto diff flags breaking changes in any pull request, pacto impact names the consumers they break once Pacto can see your fleet, and eBPF checks what is actually running.

The demo runs in your browser and downloads about 5 MB. Pacto is for the teams who operate many services; start with what Pacto is.

Know which services a change breaks before it ships.

What is Pacto?

Pacto tells you which services a change breaks before it ships, and checks what is actually running. You describe each service once, in a contract: one YAML file that says who owns the service, what it offers, which services it calls and which of their versions it accepts. It lives in the OCI registry you already run. pacto diff says whether a change is breaking and pacto impact says which consumers it breaks once Pacto can see your fleet. The runtime checks compare a running service with its contract.

When you are ready, Pacto's opt-in delivery component (alpha, Kubernetes) ships the changes the contract graph clears. Flux or Argo CD still apply every version. GitlessOps means signed artifacts in your registry and evidence decide which version runs where, while your code and manifests stay in git. Delivery starts by watching and climbs the autonomy ladder, from observe (watch only) to autonomous, set per Stage. A person confirms every step up. A change that breaks a consumer waits for that consumer's owners, and when Pacto cannot see enough it says Unknown and waits for a person.

A contract looks like this:

pacto.yaml
pactoVersion: "2.0"

service:
  name: checkout
  version: 4.2.0
  owner: { team: commerce, dri: alice }

interfaces:
  - name: rest-api
    type: openapi
    ref: interfaces/openapi.yaml       # the OpenAPI document you already maintain
    visibility: public

dependencies:
  - name: auth
    ref: oci://ghcr.io/acme/auth-pacto
    required: true
    compatibility: "^2.0.0"            # the range this revision accepts

Who breaks when a dependency ships a new version

The compatibility range above records which versions of auth this revision accepts. Each consumer's range lets Pacto answer per consumer when auth is about to ship 3.0:

$ pacto impact ./auth-2.1.0 ./auth-3.0.0 --local .
Impact: auth 2.1.0 -> 3.0.0
Classification: BREAKING
Breaking changes: 1
Potentially breaking changes: 0
Affected consumers (2):
  checkout                     direct     confidence=contractual  compat=incompatible owner=commerce
  reporting                    direct     confidence=contractual  compat=compatible   owner=analytics
    note: compatible only means the range >=2.0.0 <4.0.0 accepts 3.0.0; this change is BREAKING, so check that reporting does not use what it removes or changes
Release gate: unverified
unverified: the change is BREAKING and 2 consumers depend on auth, but none is shown to be both incompatible and running. Review each consumer, and add a source that knows where services run (for example --target-state) to tell deployed impact apart

pacto diff lists the breaking change itself. checkout accepts ^2.0.0 and 3.0.0 falls outside it. reporting accepts >=2.0.0 <4.0.0 and 3.0.0 is inside, though a range match does not prove reporting avoids what changed. direct means each one declares auth itself. contractual means the answer comes from the declared ranges alone, without a runtime observation of the call. The folder says nothing about where the consumers run, so the release gate is unverified and the command exits 2.

See who breaks in CI for the sources pacto impact needs.

You check one file when you write it, compare it with the previous revision and then compare it with what is running.

What each command answers

Command Question it answers
pacto validate Is this contract legal?
pacto diff Is my change breaking for anyone who uses it?
pacto impact Which consumers, and where do they run?
The operator, a controller you install in the cluster Does reality still match what was declared?

validate and diff pay off at one service; impact and the graph of who calls whom pay off at the second consumer.

Check what is actually running

Pacto checks what a running service does on the network against what its contract says, on Linux, and reports only what it can confirm:

What it catches Finding
A process reports healthy but nothing listens on the declared port INTERFACE_ABSENT
A declared dependency the service keeps failing to reach DEPENDENCY_UNREACHABLE
A call to another Pacto service no dependency declares (seen by the node agent or pacto agent; a warning, so the contract reads Warning rather than NonCompliant) DEPENDENCY_UNDECLARED
pacto run --contract ./payments --bind api=8080 --fail-on noncompliant -- ./payments-server

Pacto watches TCP connections in the Linux kernel with eBPF (small, safe programs the kernel runs on events). The kernel watcher reads connection metadata, never payloads or secrets. The optional probes read only the response they need. When it cannot see something, it says so. Run it three ways: pacto run wraps one command (a laptop, a CI job), pacto agent watches a Docker host or a server and the Kubernetes operator can deploy the same agent on every node (opt-in). See Runtime conformance for the kernel and privilege requirements.

What delivery needs

Contracts work anywhere, and the checks above work on Linux. Delivery, the part that moves versions, is alpha: its settings and commands may still change. It needs:

  • Kubernetes 1.30 or later, with Flux (Argo CD works too, as an experimental option).
  • Your container registry, to hold contracts and versions.
  • For signed records, and so for the two automatic levels, a registry that serves the OCI Referrers API: the feature that lets a registry list the files attached to an image, here the signed records. zot, an open source registry, serves it. GitHub's registry does not serve it today, so a Stage that uses it stays on observe or advise. For any other registry, check its documentation for "referrers API".
  • For checks on error rates after a release, traces in Mira, an OpenTelemetry trace store, or a check you call over HTTP. Without them Pacto still checks the contract.
  • For a person to approve anything, a cluster that can tell how recently that person signed in to your company login. That works where you set the Kubernetes API server's flags yourself (tested on kind). EKS, GKE and AKS are not verified yet. Where it does not work, nobody can approve, so no Stage can move up the ladder. See where approving works.

To try it, start a new service on observe, where Pacto moves nothing, or open the live demo in your browser.

Agents take the same path

An AI agent asks for a delivery change over MCP the way a person or a CI job does: it creates an Operation, and the promoter plans and checks it. Agents get no approve tool, and the admission policies the chart installs with delivery refuse an approval from an agent. Kubernetes RBAC still governs what the agent's identity may do outside Pacto. Agents take the same path says what the policies close and what your platform closes itself. The delivery security model gives the detail.

Where to start

You want to Read
Know what Pacto is and whether it fits Why Pacto, Who breaks when a dependency ships, How Pacto relates to other tools and the live demo
Give many existing services a contract Generate contracts from what you already have
Pactify your first service (give it a contract and connect it to delivery) Quickstart, then Pactify a service
Approve or unblock a change Decide, unfreeze and roll back
Verify a record Check a record without Pacto
Drive Pacto from an AI agent AI assistants (MCP)
Write and check contracts For developers and the contract reference

New words are explained in the glossary.

Pacto delivery builds on Flux's Gitless GitOps, ConfigHub's configuration as data and Anthropic's Scion; the manifesto says what it takes from each. The contract graph is ours, and all of Pacto is open source under the MIT licence.