Skip to content
pacto

Open contract standard

One contract for every cloud-native service

A single YAML contract declaring how a service is meant to behave — validated, versioned, distributed through any container registry, and checked against what is actually running.

The demo runs entirely in your browser — about 11 MB, nothing to install. Pacto is for the teams who operate many services; it is also worth knowing what Pacto is not.

One contract for every cloud-native service

pacto.yaml
pactoVersion: "2.0"                       # the contract format, not the CLI version

service:
  name: payments-api
  version: 2.1.0
  owner: { team: payments, dri: alice }   # dri: directly responsible individual

interfaces:
  - name: rest-api
    type: openapi
    ref: interfaces/openapi.yaml
    visibility: public

dependencies:
  - name: auth
    ref: oci://ghcr.io/acme/auth-pacto:2.0.0
    required: true
    compatibility: "^2.0.0"

workload: service

state:
  type: stateful
  persistence: { scope: shared, durability: persistent }
  dataCriticality: high

One file, checked and shipped

Everything above is validated (structure, cross-references and policy), versioned with semver — semantic versioning, the MAJOR.MINOR.PATCH scheme — and distributed as an OCI (Open Container Initiative) artifact: the same registries that already hold your container images.

What is Pacto?

Pacto (/ˈpak.to/ — Spanish for pact) is the machine-readable operational contract for a service. It captures what a platform, a pipeline or an agent needs to know about a service — its identity and ownership, the interfaces and capabilities it exposes, its state model, its dependencies, its configuration and the policies that apply to it — in one versioned YAML file that machines can validate and tooling can consume, instead of reassembling it from Helm values, OpenAPI, Kubernetes manifests and READMEs.

Pacto doesn't invent a new configuration language. An interface is an OpenAPI document, an AsyncAPI document or a gRPC service descriptor you already maintain, and a configuration is the JSON Schema you already publish — Pacto composes the interfaces you already have instead of redefining them. On top of that it adds what no single schema can express: how interfaces relate, what they depend on and how they change over time.

The contract states stable operational intent. It is deliberately not a deployment manifest and not a snapshot of every runtime detail — how a service is scheduled, scaled and wired stays with the platform, and what reality currently looks like is an observation gathered separately and evaluated against the contract. Pacto is an operational contract system made of three products:

  • CLI (command-line interface) — author, validate, diff, explain and publish contracts
  • Dashboard — see operational state, the service inventory, the operational graph and change analysis visually
  • Kubernetes Operator (optional) — one runtime evidence source that verifies live workloads still match the contract

No sidecars. No new distribution plane. The CLI runs at build time and CI time.

Underneath those products is one modelauthor → publish → observe → evaluate → consume: the contract declares intent, a collector observes an environment and emits evidence — observed facts about a running system, gathered outside the contract and never written into it — a pure engine evaluates the contract against that evidence, and consumers surface or act on the result. The Kubernetes operator hosts the first shipped collector; anything that produces valid evidence can be one. An environment Pacto cannot watch — an edge site, an air-gapped estate, a CI runner — signs and reports its own evidence inbound instead, over the external evidence protocol. See Collectors and the evidence boundary.


What Pacto is not

  • Not a deployment tool — it describes what to deploy, not how
  • Not another configuration language — see above: it points at the schemas you already maintain
  • Not a registry — it uses existing OCI registries (GHCR, ECR, ACR, Docker Hub)
  • Not a service catalog — it produces the structured data that a catalog (Backstage, Port, Cortex) could consume
  • Not an IDP, portal or authorization system — it is the machine-readable operational layer over an Internal Developer Platform (IDP), not the portal humans click or the system that decides who may act

The problem

Today, a cloud service is described across six different places — none of which talk to each other:

OpenAPI spec    → describes one interface, but not the service
Helm values     → describes deployment, but not the service's intent
env vars        → documented in a wiki (maybe), validated never
K8s manifests   → health checks and wiring, no link to a service definition
Dependencies    → tribal knowledge in Slack threads
README.md       → outdated the day it was written

If any of these are familiar, Pacto is aimed at you:

  • Platforms guess service behavior. Is it stateful? Does it need persistent storage? What does it depend on?
  • Dev ↔ Platform friction. Developers ship code; platform engineers reverse-engineer how to run it.
  • Breaking changes are detected too late. A removed endpoint or a dropped dependency breaks production, not CI.
  • No dependency visibility. No one knows what depends on what until something breaks.
  • Onboarding is slow. Every new service starts another round of reverse-engineering.

The contract at the top of this page answers all six sources at once. Only pactoVersion and service are required; every other section is opt-in, so a contract stays as small as the service needs — that example declares no configurations, capabilities, policies or readiness because that service does not need them. See the contract reference for every field.


Who is Pacto for?

Developers

Define your service's operational interface alongside your code. Declare interfaces, configuration schema, health checks and dependencies. Validate locally before pushing. The developer guide

Platform engineers

Consume contracts to generate deployment manifests, enforce policies, detect breaking changes and build dependency graphs — deterministically and automatically. The platform engineer guide

Building a platform on Pacto?

These primitives compose into reusable platform patterns — root + component contracts for monorepos, infrastructure contracts with provisioner metadata, configurations as composable claims, platform-published policy + schema bundles, progressive policy versioning and per-environment override files. See Composition Patterns.


From one contract to an operational graph

A single contract describes one service. Composed across a whole platform, those contracts, their revisions and their targets — a revision being one immutable published version of a contract, a target one concrete place a revision runs, such as a workload in one cluster — become a versioned, verifiable operational graph that humans, automation and agents can reason over.

Think of it against an Internal Developer Platform (IDP). An IDP makes platform capabilities consumable by humans through portals, golden paths, catalogues and workflows. Pacto makes platform knowledge consumable by machines through contracts, relationships, constraints, tools and evidence. See The Pacto Operational Graph and Concepts for the distinctions that graph is careful never to collapse.


What consumes a contract?

A contract is written once and read by every system that needs to understand the service. (For the people, see Who is Pacto for? above.)

  • Platform engineering — controllers and generators consume the contract to provision infrastructure, wire networking and gate promotion, instead of reverse-engineering a service from its Helm chart.
  • CI pipelinespacto diff classifies breaking changes and pacto validate enforces policy before a merge or a publish.
  • Runtime controllers — the Kubernetes operator observes live workloads and reports whether reality still matches the declared contract.
  • Autonomous agents — because the contract is machine-readable, an agent can discover what a service is and what it can do rather than infer it. pacto mcp projects a bundle's operations into callable tools over the Model Context Protocol; MCP is one integration surface, not the definition of Pacto.

Pacto is useful without any agents at all — the diff, graph, policy and verification loops stand on their own. Agents do not justify the contract; they raise the cost of not having one. See the MCP Integration guide.


How it works — 30 seconds

1. Developer writes a pacto.yaml alongside their code
2. pacto validate checks it (structure, cross-references, policy)
3. pacto push ships the contract to an OCI registry as a versioned artifact
4. pacto dashboard shows operational state, the graph and change analysis
5. The Kubernetes operator verifies runtime stays faithful to the contract

What's inside a Pacto bundle

graph LR
    subgraph Bundle["Pacto Bundle"]
        direction TB
        YAML["pacto.yaml<br/><i>required</i>"]

        subgraph Sections["Contract Sections <i>(all optional)</i>"]
            direction TB
            Interfaces["Interfaces<br/>openapi · asyncapi · grpc · visibility"]
            Dependencies["Dependencies<br/>oci://auth:2.0.0 · oci://db:1.0.0"]
            Runtime["Runtime<br/>workload · state · capabilities"]
            Config["Configuration<br/>schema.json"]
            Policy["Policy<br/>schema.json"]
        end

        subgraph Extras["Metadata <i>(optional)</i>"]
            direction TB
            Docs["docs/<br/>README · runbooks · guides"]
            SBOM["sbom/<br/>SPDX · CycloneDX"]
            Skills["skills/<br/>agent domain knowledge"]
        end

        YAML --> Sections
    end

    Bundle -- "pacto push" --> Registry["OCI Registry<br/>GHCR · ECR · ACR<br/>Docker Hub"]

A bundle is a self-contained directory (or OCI artifact): pacto.yaml (required) plus optional interfaces/, configuration/, policy/, docs/, sbom/ and skills/ directories, holding the schemas you already maintain. Validation enforces that every schema a contract points at exists in the bundle and parses — interfaces[].ref, configurations[].schema and policies[].schema. Free-form pointers are not resolved: a readiness claim may cite a runbook, a ticket or a URL, and Pacto checks that the citation is non-empty, never that its target exists. See the contract reference for the full bundle layout and validation layers for every rule.


Key capabilities

  • 3-layer validation — structural (JSON Schema), cross-field (reference and consistency checks including state vs. persistence) and policy enforcement
  • Breaking change detectionpacto diff compares two contract versions field-by-field and resolves both dependency trees, so a change inside a dependency is classified too. It looks down the tree; pacto impact is the one that looks up it, naming the consumers a breaking change would reach. Worked output, read line by line
  • Dependency graph resolution — recursively resolve transitive dependencies from OCI registries; sibling deps are fetched in parallel
  • OCI distribution — push/pull contracts to any OCI registry: GitHub Container Registry (GHCR), Amazon Elastic Container Registry (ECR), Azure Container Registry (ACR), Docker Hub, Harbor; bundles are cached locally for fast repeated operations. A contract is an ordinary OCI artifact and needs nothing special; storing evidence beside it does — see registry requirements, which GHCR does not currently meet
  • Plugin-based generationpacto generate invokes out-of-process plugins to produce deployment artifacts from a contract
  • Rich documentationpacto doc generates Markdown with architecture diagrams, interface tables and configuration details
  • SBOM diffing — an optional software bill of materials (SBOM) in SPDX or CycloneDX format with automatic package-level change detection on pacto diff
  • Operational dashboardpacto dashboard launches a web UI organised around four workflows — an operational Overview, the Services inventory, the Operational graph and Change analysis — across local, OCI and Kubernetes data sources
  • Runtime fidelity verification — the optional Kubernetes Operator continuously checks that deployed services match their contracts across seven dimensions — workload, persistence, interfaces, dependencies, configuration, health and metrics — and reports what it could not observe as Unknown rather than guessing. Two are narrower than they sound on a Helm install: health falls back to passive readiness signals, and metrics reports Unsupported, because the chart renders no flag that turns either on
  • AI assistant integrationpacto mcp serves contracts to Claude, Cursor and GitHub Copilot over MCP: authoring tools, read-only operational-graph queries, blast-radius analysis, and a bundle's own API operations as callable tools

What you keep if you stop using Pacto

Pacto invents three files — pacto.yaml, the pacto.lock that pacto lock writes, and an optional .pactoignore — and nothing outside Pacto reads any of them. That is the whole of the lock-in. Everything those files wrap stays yours, and that is checkable rather than a promise:

  • The contract source is yours already. pacto.yaml and the files beside it are plain YAML and JSON living in your repository, and the interfaces inside are the OpenAPI, AsyncAPI, gRPC and JSON Schema documents you maintained before Pacto existed. Delete the tooling and those files are unchanged.
  • The registry is yours already. Pacto is not a registry; a published bundle is an ordinary OCI artifact in your own GHCR, ECR, ACR or Artifactory. Nothing is stored on infrastructure operated by the project.
  • A published bundle opens without Pacto — it is a gzipped tar layer, so standard OCI tooling is enough to get the files back out (below).
  • Removing the runtime side leaves your workloads untouched. The operator observes and never modifies them, so uninstalling it stops the checking and leaves every workload exactly as it was. It does take Pacto's own components with it — the managed dashboard and Evidence Server are garbage-collected along with the controller — and a few cluster-scoped objects outlive the release and need deleting by hand. Both removal paths, and every object that survives them, are written down: uninstall the CLI and uninstall the operator.

Unpacking a published bundle with no Pacto binary anywhere in reach — this needs oras and jq, neither of which is a Pacto tool:

REPO=ghcr.io/your-org/your-service
TAG=1.0.0
DIGEST=$(oras manifest fetch "$REPO:$TAG" | jq -r '.layers[0].digest')
oras blob fetch --output bundle.tar.gz "$REPO@$DIGEST"
tar -xzf bundle.tar.gz    # pacto.yaml, interfaces/, configuration/, sbom/

pacto pull writes the same files and is the easier route while you still have the CLI.

What you lose by leaving is the checking — the validation, the change classification, the operational graph and the compliance verdicts. What you lose is never the data.


Where to go next

Ready to try it? The live dashboard demo puts the whole dashboard in your browser, against a fixture fleet, with nothing to install — and the Docker Compose demo runs a real one on your own machine. When you want your own contract, the Quickstart takes about five minutes from an empty directory to a published bundle. To understand the system rather than drive it, read the Pacto model; for the positioning and rationale behind it, the Manifesto.

Getting help

Pacto is MIT licensed and developed in the open at github.com/TrianaLab/pacto. There is no commercial support offering and no paid support channel; the routes that exist are these:

  • Something is broken, or a document is wrong — report a bug on the issue tracker, which has a bug-report template. Every documentation page also has an edit pencil that opens a pull request against its source.
  • A security vulnerability — use a private advisory, never a public issue.
  • Something is behaving oddly rather than failing — the Kubernetes troubleshooting guide and the MCP troubleshooting section cover the diagnosable cases, including the ones where Pacto reports Unknown because it genuinely cannot observe something.