API Integration

What you'll accomplish: Understand the two ways Hoziron exposes an external API as agent-usable tools, install and manage the integration lifecycle, and know what's actually implemented today versus what the package format anticipates.

Two mechanisms, one lifecycle

MechanismPackage payloadUse for
MCP serverpayload/mcp.jsonAn API that already has (or can have) an MCP server in front of it
REST/SOAP adapterpayload/adapter.json + payload/transforms/*.starA carrier API you're wrapping directly — REST or SOAP, no MCP server involved

Both are integration-type packages (hoziron-cli package init --type integration ...), installed and managed identically:

hoziron-cli catalog install guidewire-claimcenter
hoziron-cli integration connect guidewire-claimcenter
hoziron-cli integration status guidewire-claimcenter
hoziron-cli integration tools guidewire-claimcenter
hoziron-cli integration disconnect guidewire-claimcenter
hoziron-cli integration reconnect guidewire-claimcenter

Installing an integration-type package through the catalog auto-registers it — there's no separate registration step. connect starts the underlying server process (MCP) or activates the adapter (REST/SOAP); disconnect/reconnect stop/restart it; status and tools are read-only.

Per ADR-044's lifecycle contract, an integration's runtime state is ephemeral, re-derived from its definition on boot — unlike an agent or workflow, there's nothing durable to resume; connect/disconnect/reconnect just start/stop a process or connection.

hoziron-cli add <name> --key <key> exists as a "one-click" shortcut but currently posts straight to /integrations/install with name treated as a source path — it isn't wired to resolve a catalog package name first. For a package published to a registry, use hoziron-cli catalog install <name> (which does auto-register), not hoziron-cli add.

MCP servers

An MCP-backed integration package declares one or more contracts — named, swappable tool surfaces — in its manifest:

[contracts.claims-core]
provides = ["claim.search_history", "claim.create", "claim.update",
            "claim.set_status", "claim.attach_document", "claim.assign"]

[contracts.policy-admin]
provides = ["policy.lookup", "policy.verify_status", "policy.get_coverage",
            "policy.get_insured", "policy.get_risk_units"]

A competency then declares what it needs, using contracts: for a swappable backend (the carrier's actual claims-core system varies by deployment) or integrations: for a fixed, universal MCP (a public-utility server with no carrier variant):

contracts:
  - policy-admin
  - claims-core
integrations:
  - google-search

At equip time, contracts: resolves to whichever installed integration currently declares that contract; integrations: binds directly to the named package. This is what makes a competency carrier-portable: onboarding a new carrier is "install one package declaring the needed contracts," not "edit every competency that used to talk to the old system." See ADR-051.

Known contracts from the reference (testbed) implementation:

ContractTools
policy-adminpolicy.lookup, policy.verify_status, policy.get_coverage, policy.get_insured, policy.get_risk_units (all read)
claims-coreclaim.search_history, claim.create, claim.update, claim.set_status, claim.attach_document, claim.assign (claim.create carries the FNOL value-event signature write)
notifynotify_send_sms, notify_send_whatsapp, notify_send_email (all write)

At connect time, the platform validates that a contract-providing server actually exposes every tool in its declared provides — a gap is a loud error at connect/equip time, not a runtime timeout discovered later. Only tool names are checked (parameter/return-shape conformance is deferred, not yet enforced).

REST/SOAP adapter packages

For a carrier system with no MCP server — a direct REST or SOAP integration package (ADR-057) ships a JSON contract instead of mcp.json:

my-carrier-adapter/
├── MANIFEST.toml              # type = "integration"
└── payload/
    ├── adapter.json            # the contract
    └── transforms/
        ├── claim_create_phase1_body.star
        └── claim_create_phase1_identity.star
{
  "integration": {
    "name": "guidewire-claimcenter",
    "transport": "rest",
    "base_url": "${CARRIER_CC_BASE_URL}",
    "auth": { "kind": "bearer", "token_env": "CC_OAUTH" },
    "env": { "CARRIER_CC_BASE_URL": "" }
  },
  "ops": {
    "policy_verify_status": {
      "access": "read",
      "kind": "single",
      "method": "GET",
      "path": "/claim/v1/claims/{claimId}/policy",
      "extract_response": "transforms/policy_verify_status_response.star"
    }
  }
}

integration.env is a declared allowlist for what base_url may pull from ${VAR} — a var referenced but not declared here is a validation error, closing an ambient-env-var exfiltration path. Every build_body/extract_identity/extract_response hook is optional; an op with no build_body passes call arguments straight through as the request body.

The contract carries no PII-specific fields, deliberately — detection is content-based and transport-blind at the mediation seam, never declared by the package author. See PII Engine.

What's actually live today (Issue #587)

Be precise about this with anyone building against it — the format is broader than current dispatch:

  • Only kind = "single" ops dispatch. two_phase, async_callback, and SOAP are rejected with a clear error, both at catalog install time (a REST contract with zero single-kind ops fails install outright) and at call time — never silently mishandled.
  • Only auth.kind = "none" and "bearer" are implemented. "bearer" sends the resolved token_env value as a literal Authorization: Bearer <token> header. oauth2_client_credentials, basic, and api_key — despite appearing in the ADR's own illustrative example — are rejected at connect time rather than silently sent as a Bearer token.

Two-phase dispatch, SOAP, and OAuth2 token exchange are real, tracked follow-up work (Issue #587), not permanent limitations — but don't build a package today assuming they work.

Testing an integration

# Confirm the process/connection is live
hoziron-cli integration status guidewire-claimcenter

# See what tools it actually exposes
hoziron-cli integration tools guidewire-claimcenter

Next steps


Related: