Existing stack

[ AxiomCore · Documentation ]

How extraction works

What a backend extractor reads and executes, where the CLI finds it, and how to review an extracted contract.

Extraction turns a supported backend's routes and models into Acore declarations that your axiom.acore can amend. This page explains what each extractor reads and runs, so you can decide where extraction is safe to run and what you still need to review.

Supported inputs

InputStatusWhat you get
FastAPIAvailableRoutes, parameters, Pydantic models with field validation, relationship candidates
GoAlphaRoutes and types for Chi, Gin, Echo, Fiber, gorilla/mux and net/http patterns; review framework-specific constructs
OpenAPI JSONExperimentalA reviewable domain block from axiom domain bootstrap --source openapi; not a complete import of every vendor extension or Acore behavior
SQL DDLExperimentalA reviewable domain block from axiom domain bootstrap --source sql; it does not connect to or manage a live database
Other backend frameworksComing soonNo supported extractor workflow

The published extractor binaries are for macOS arm64.

How the CLI runs an extractor

A backend source starts with an amends line that names a module and an entrypoint, for example amends "axiom-fastapi:main.py:app". Each time you run axiom eval, check, explain or build on that file, the CLI runs the extractor again.

One build: the CLI runs the extractor, then applies your Acore declarations
One build: the CLI runs the extractor, then applies your Acore declarations
Diagram source
sequenceDiagram
  participant Dev as You
  participant CLI as Axiom CLI
  participant Ext as Extractor
  participant Src as Backend source
  Dev->>CLI: axiom build axiom.acore
  CLI->>Ext: Run with the entrypoint
  Ext->>Src: Import or load the code
  Ext-->>CLI: Routes and models
  CLI->>CLI: Apply axiom.acore
  CLI-->>Dev: .axiom contract

The FastAPI extractor imports your app; the Go extractor loads your packages. Either one reports routes and models. The CLI converts them into declarations, applies everything else in your axiom.acore, and writes the contract. The CLI finds each extractor in a fixed place:

Module in amendsBinary the CLI runsOverride variablePublished release asset
axiom-fastapi:<file>:<app>~/.acore/bin/axiom-fastapi-extractorAXIOM_FASTAPI_EXTRACTORaxiom-fastapi-macos-arm64 in extractor-fastapi-v0.1.4
axiom-go:<file>~/.acore/bin/axiom-go-extractorAXIOM_GO_EXTRACTORaxiom-go-extractor-macos-arm64 in extractor-go-2026.10.14.2

If the binary is missing, evaluation fails with MISSING_EXTRACTOR: fastapi-extractor or MISSING_EXTRACTOR: go-extractor. Install both with the steps in backend extractors; in CLI 0.149.1, axiom install <extractor> --module does not find the published builds.

What each extractor executes

FastAPI extractorGo extractor
How it reads your codeImports the entry module to get the FastAPI instanceLoads your packages and resolves their types with your Go toolchain
Your code that runsThe entry module's top-level code and every local module it importsNone: it does not run main or handlers
DependenciesBundles FastAPI, Starlette and Pydantic; does not use your virtual environmentNeeds a Go toolchain on PATH; downloads missing modules unless you ran go mod download
Missing third-party packagesReplaced with inert placeholders, so extraction continuesResolved by the Go toolchain, as above

Two consequences for FastAPI:

  • Import-time effects are real. A local module that writes a file, opens a connection with the standard library, or starts work at import does so every time the contract is evaluated or built.
  • Placeholders hide behavior. Calls into a package the extractor does not bundle return placeholders instead of running. Models or types that come from such packages can extract incompletely, so review them.

Prefer an application factory, or a module whose import only declares the app, routes and models. Move migrations, worker startup, external connections and destructive setup behind explicit process entry points. For example:

src/main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health() -> dict[str, str]:
    return {"status": "ok"}

After you install the FastAPI extractor, create and build its contract from the directory that contains src/:

Terminal
axiom init ./src/main.py:app --module axiom-fastapi
axiom build axiom.acore --out backend.axiom

Treat backend source as code at the extraction boundary

There is no universal no-execution guarantee. A CI runner can be smaller than your production environment, but it still needs the extractor binary, the Go toolchain for Go, and an import path that is safe to execute. Do not give the extraction step production credentials.

What extraction cannot see

An extractor reports what it can observe. It cannot prove the business meaning of a handler. For example, a FastAPI path parameter declared with Path(max_length=40) is extracted as a plain required string; FastAPI still returns 422 for longer values, but the contract does not say so. The same applies to checks written inside Go handlers and to routes built dynamically.

To bootstrap domain declarations from other inputs, run axiom domain bootstrap --source openapi <file> or axiom domain bootstrap --source sql <file>. The result is written to axiom.domain.acore unless you pass --output, and is a suggestion to review, not runtime parity.

Review before release

  1. Inspect the extracted or amended endpoints and models with axiom inspect backend.axiom or axiom explain axiom.acore.
  2. Confirm authentication, permissions, validation and error declarations.
  3. Add policies or explicit Acore declarations where the source evidence is incomplete.
  4. Run contract tests against a controlled service or a mock.
  5. Inspect the semantic diff against the version your consumers use, with axiom diff --format semantic.

Next steps