Skip to content

Architecture

Anvil captures source contracts, combines them with reviewed policy, and compiles AIR into CLI, MCP, SDK, and supporting artifacts. This page maps those stages to packages and explains where validation and execution occur.

Start with the product boundary to distinguish contract compilation, offline legacy evidence, and runnable bridge support.

The architecture protects seven invariants:

  1. One semantic model. CLI, MCP, skill, client SDKs, hooks, mocks, and deployment inputs are projections of AIR, not separate sources of truth.
  2. Captured inputs. Compilation reads a content-addressed source snapshot, not a mutable remote contract.
  3. Conservative safety. Unknown mutation semantics cannot become callable by default.
  4. Approval controls exposure. Only approved operations enter callable projections.
  5. Runtime enforcement remains authoritative. A missing harness hook cannot remove a safety requirement.
  6. Evidence binds to bytes. Assurance records identify the bundle hash they tested and become stale after change.
  7. Legacy discovery is not execution authority. A technical candidate or approved binding cannot imply that a runtime bridge exists.
StageInputResponsibilityOutput
Source captureFiles or a source directoryDetect entrypoints, follow permitted local references, reject path escape, store verbatim bytesImmutable source snapshot
Protocol adaptationOne locked entrypointLower OpenAPI, Swagger, GraphQL, proto3, WSDL, Discovery, OData, Postman, or a HAR capture into the shared HTTP-shaped compiler inputNormalized source document
Semantic compilationAdapted document plus optional manifestNormalize operations, classify effects, apply reviewed facts, validate safety, discover capabilitiesAIR document
ProjectionAIRGenerate CLI, MCP, skill, client SDKs, hooks, mocks, evals, runtime documents, targets, and deploy inputsBundle directory
ReviewBundleInspect diagnostics, enrich missing facts, review capabilities, approve operationsReviewed bundle
AssuranceOne immutable bundleCheck static identity, exercise transport, compare surfaces, simulate safety behaviorHash-bound evidence records
Release planningAssured bundle plus target inputsVerify required evidence and emit an operator planPublication plan; no deployment

anvil agentify orchestrates the first four discovery activities—capture, compile, assess, and capability proposal—then stops for review.

Legacy mode does not pass deployment descriptors or broker configuration through the API protocol adapters. It uses a separate evidence model:

StageInputResponsibilityOutput
Offline acquisitionCaller-supplied file or hardened-expanded directoryBound filesystem reads and preserve provenanceRelative member paths and bytes
CollectionJava EE, .NET, or messaging membersParse only declared configuration; hash opaque binariesArtifacts, evidence, observations, diagnostics
ReconciliationVerified inventory snapshotGroup exact coordinate and invocation matches; retain every assertionTechnical candidates and explicit conflicts
Task creationOne exact candidateFreeze required decisions and non-negotiable policyContent-addressed harness task
Harness proposalTask plus external evidence accessPropose business schema, errors, transport, and operational semanticsUntrusted submission bound to the task
Assessment and reviewInventory, task, proposal, human decisionVerify lineage and completeness; keep approval separateAssessment, receipt, and reviewed binding

Candidates are reconciliation products, not AIR operations. The approved binding records runtime.placement = deployment_local_bridge and runtime.status = not_implemented. No generator or runtime currently consumes it as executable input.

This deliberate gap prevents the compiler architecture from implying that configuration parsing also solved vendor client compatibility, field mapping, transactions, identity, network placement, or completion semantics.

Source capture is intentionally separate from parsing. The store records:

  • verbatim file bytes;
  • discovered entrypoints and formats;
  • the role of each file in the graph;
  • external references that were observed but not fetched;
  • structured diagnostics;
  • a content-derived snapshot id and source hash; and
  • optional origin metadata such as a gateway vendor.

Local references must remain inside the import root. Remote references are not fetched. A malformed input can be preserved as an invalid snapshot for diagnosis, but only a valid snapshot can enter the compiler.

This separation answers a foundational question: which exact bytes did the compiler read? Later evidence can bind to that identity rather than to a path or URL that may have changed.

The downstream compiler consumes one internal document shape. Protocol adapters perform deterministic lowering before semantic normalization:

AdapterMapping
OpenAPI 3.xParsed and dereferenced directly
Swagger 2.0Upgraded with swagger2openapi, then parsed as OpenAPI
GraphQL SDLRoot fields become POST-shaped operations; GraphQL kind carries read/mutation meaning
gRPC/proto3RPCs become operations; messages and enums become JSON schemas
SOAP/WSDL 1.1portType operations become POST-shaped operations; WSDL/XSD types become schemas
Google DiscoveryResource methods and schemas become paths, operations, and components
OData v2/v4Entity sets become permitted CRUD operations based on metadata
Postman v2.xSaved requests, folders, examples, and auth shapes become an API document
HAR 1.2 captureRecorded requests become templated operations; every operation is capped review_required — a capture is evidence, never a declared contract

Adapters own syntax and mechanical fidelity. They do not grant business authority. A method named TransferFunds remains a mutation whose idempotency must be established by evidence or a reviewed manifest.

See Source format support for exact boundaries.

AIR—the Anvil Intermediate Representation—is defined with Zod in @anvil/air. One document contains the service, operations, capabilities, workflows, shared schemas, evidence, and diagnostics.

Each operation carries:

AxisExamples
Identitystable id, source reference, canonical name
Effectread or mutation, action, risk, reversibility
Repeatabilityidempotency mode, key location, retry eligibility
Intent gateconfirmation requirement, human-approval tier, reason
Accessauth type, principal, scopes, credential profile, carrier
Interfaceinput/output schemas, parameters, errors, pagination
ProjectionCLI command, MCP tool name, skill intents
Lifecyclegenerated, review required, approved, blocked, deprecated
Ownershipcapability and workflow relationships
Evidenceclaim-scoped provenance, confidence, reliability, review state

Evidence is recorded per semantic claim. A strong claim that an endpoint exists must not increase confidence that it is idempotent. The reconciler evaluates confidence by predicate and uses asymmetric trust:

  • loosening safety requires strong evidence;
  • tightening safety can proceed on weaker warning evidence; and
  • conflicting safety-sensitive claims choose the safer posture and require review.

The aggregate confidence shown for an operation is descriptive. Safety gates use the relevant claim, not a blended score.

A capability groups related operations. Discovery uses source structure such as tags and resource names and records provenance for the grouping. A capability has its own review lifecycle and disclosure budget.

Workflows are authored, not guessed. Each step references an existing operation; an unresolved reference or unapproved mutation blocks the workflow. A workflow cannot grant authority that its steps do not have.

The semantic compiler applies ordered passes:

  1. Normalize source operations into stable AIR identities and schemas.
  2. Classify effect, action, risk, idempotency, retry, confirmation, auth, and pagination conservatively.
  3. Apply manifest facts and reviewed decisions.
  4. Recompute derived policy so idempotency, retries, confirmation, and effect remain coherent after overrides.
  5. Validate invariants and force unsafe or uncertain operations into review_required or blocked.
  6. Discover capabilities and attach authored workflows.
  7. Generate diagnostics and evidence for every material decision.

The manifest wins where it explicitly supplies a value. Unset fields are recomputed; stale derived values are not retained merely because a nearby field changed.

@anvil/generators treats AIR as read-only input and emits independent views:

  • operation catalog and compiled runtime documents;
  • typed CLI;
  • MCP server and resource index;
  • skill package and operation references;
  • shared hook core plus harness adapters;
  • mock server, evals, and conformance assets;
  • target-specific connector kits;
  • Cloud Run and infrastructure inputs; and
  • certification metadata.

The bundle installer stages generated output, verifies surface agreement, and swaps the complete candidate into place. Partial projection updates are not a supported state.

The deployed unit is the generated MCP server backed by @anvil/mcp-runtime and @anvil/runtime. It does not parse source specifications or run enrichment. anvil serve mcp <dir> serves one bundle per process; anvil serve mcp <workspace-root> --fleet mounts every bundle beneath a workspace root onto one MCP surface instead, each under a stable per-bundle tool-name prefix, composed from independently-built single-bundle servers rather than a second serving path — see fleet.md.

Before an upstream call, the executor evaluates the following controls in a deterministic order:

ControlPurpose
Input validationReject arguments outside the generated schema
ConfirmationRequire explicit intent for gated effects
IdempotencyRequire and fingerprint deduplication keys where configured
Principal scopeRefuse a caller missing a scope auth.scopes requires (fleet runtime; anonymous/every-scope by default)
Rate/spend limitsRefuse a caller over its configured per-principal rate or spend budget (fleet runtime; unlimited by default)
Dry runReturn a redacted request plan after preconditions pass
Host pinningRestrict upstream egress to reviewed hosts
Auth resolutionResolve named credential profiles without placing secrets in AIR
Ledger durabilityFail closed when a required durable write ledger is unavailable
Retry policyRetry only bounded transient conditions when repetition is safe
Response normalizationProduce structured outputs and stable error envelopes
ObservationEmit an OpenTelemetry-shaped execution record, including the calling principal’s id (never its credential)

Runtime policy hooks can deny at defined pre/post phases. They are not the same as harness hooks: runtime hooks execute inside the authority boundary, while harness hooks improve the caller experience before transport.

A horizontally scaled stateless runtime cannot keep deduplication state in process. Required-idempotency writes therefore use a pluggable durable ledger. Outside development, the runtime fails closed when the configured durable backend is unavailable.

The built-in Firestore path provides reservation, replay, conflict, and readiness behavior. It is bounded deduplication, not a claim of exactly-once execution: a crash after upstream success but before ledger completion remains an operator-reconciliation case.

Assurance is split so one green check cannot hide another class of failure:

  • Certification checks static artifact identity and contract coherence.
  • Self-test boots the generated servers and exercises approved tools over the real local MCP transport.
  • Conformance compares the operations and policy described by each surface.
  • Simulation crosses operations with applicable safety dimensions and injects mutations to prove regressions are detected.
  • Benchmarking measures discovery and callability rather than safety.

Each record names the bundle hash it evaluated. status verifies freshness and selects the next required action. publish snapshots the required evidence into a plan but performs no provider mutation.

Build-time, deploy-time, and run-time boundary

Section titled “Build-time, deploy-time, and run-time boundary”
PhaseContainsMust not contain
Buildparsers, adapters, compiler, enrichment, generators, review, assuranceproduction credential values
Deploygenerated runtime, target configuration, IAM/network/secret references, ledger contractsource parsing or LLM enrichment
Runvalidation, policy, auth resolution, ledger, upstream execution, telemetryspec compilation, capability discovery, approval changes

This boundary keeps the hot path small and reviewable. The runtime consumes compiled documents; it does not reinterpret the source contract.

PackageResponsibility
@anvil/airCanonical schemas, operation semantics, disclosure model
@anvil/compilerSource store, protocol adapters, normalization, classification, manifest, validation, drift
@anvil/grammarBounded query grammar and template analysis
@anvil/refinementDeficiency detection, readiness assessment, cases, review, enrichment plans
@anvil/generatorsBundle projections and static certification inputs
@anvil/runtimeSafety executor, auth, retries, idempotency, errors, observation
@anvil/mcp-runtimeMCP serving path, capability lanes, resource serving
@anvil/harnessEvidence-source orchestration and executable bundle drivers
@anvil/legacy-bridgeDeployment-local HTTP facade executing one reviewed legacy capability binding over one transport (queue request/reply), and its in-process conformance runner
@anvil/certificationCross-artifact and async contract checks
@anvil/simulatorScenario matrix and safety-regression mutation battery
@anvil/targetsAgent-platform connector profiles
@anvil/system-packCross-bundle system packaging
@anvil/cliCommand tree and orchestration over the libraries above

The CLI is an adapter over library APIs. Core behavior belongs in packages that can be called and tested without parsing terminal output.

The legacy collectors, inventory model, reconciliation, and refinement workflow currently live behind the Node-only @anvil/compiler/legacy package export. This entrypoint accepts caller-supplied bytes and does not acquire files or network resources itself. @anvil/legacy-bridge depends only on @anvil/air and @anvil/compiler (see packages/cli/src/boundaries.test.ts’s ALLOWED_EDGES) and is not part of the deployed MCP server’s dependency closure — it is its own deployment-local process, run and reviewed separately from @anvil/mcp-runtime.

New behavior should enter through a narrow seam:

  • new source syntax through a protocol adapter;
  • new offline legacy evidence through a non-executing collector that emits the shared legacy artifact, evidence, observation, and diagnostic model;
  • new executable legacy transport through a deployment-local adapter that consumes only reviewed bindings and cannot widen their target or semantics;
  • new generated surface through a generator;
  • new agent platform through a target profile;
  • new durable store through the ledger interface;
  • new evidence source through an MCP-published connector and structured claims;
  • new harness through a thin adapter over shared hook decisions; and
  • new assurance rule through a structured check and stable diagnostic code.

An extension may add evidence or a projection. It must not create a second semantic model or bypass approval and runtime enforcement.