AxonFlow · Schema

StepGateResponse

CompanyAI GovernanceAI AgentsPolicy EnforcementAudit LoggingComplianceMCPOpen Source

Properties

Name Type Description
decision string Gate decision
step_id string Step identifier
decision_id string Unique decision identifier for auditing
reason string Reason for block or approval requirement
policy_ids array IDs of policies that matched
approval_id string Deterministic HITL queue entry UUID of the step's current hold, present on a `require_approval` decision whose queue entry exists. A step can be held more than once: hold 1 is UUID v5 over `workflow_i
approval_enqueue string What the HITL enqueue did for this gate. Present only on a `require_approval` decision where an enqueue was attempted; omitted otherwise. A `require_approval` decision ALWAYS holds the step. This fiel
approval_url string URL for human approval (Enterprise)
policies_evaluated array All policies that were checked during evaluation (Issue
policies_matched array Policies that matched and contributed to the decision (Issue
engine string The engine that decided the step: `anchored`, the ADR-065 decision plane (PRD v11 §1.1). Omitted on a cached replay (`cached: true`), which reproduces a stored decision without deciding again.
subject_type string The type of principal the step was decided for. Omitted on a decision made before a subject was admitted, and wherever `engine` is.
policy_bundle string The digest of the policy set that decided the step. Omitted wherever `subject_type` is.
cached boolean **Deprecated (Issue #1673).** Whether this response was served from a prior decision rather than a fresh policy evaluation. Use `retry_context.gate_count > 1` instead — `cached` conflates first-call-n
decision_source string **Deprecated (Issue #1673).** "fresh" or "cached". Use `retry_context.prior_completion_status` for the distinction agents and policies actually need. Kept populated on every response for back-compat;
retry_context object
View JSON Schema on GitHub

JSON Schema

axonflow-step-gate-response-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/api-evangelist/axonflow/main/json-schema/axonflow-step-gate-response-schema.json",
  "title": "StepGateResponse",
  "x-generated": "2026-10-09",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/axonflow-orchestrator-openapi.yml#/components/schemas/StepGateResponse",
  "type": "object",
  "properties": {
    "decision": {
      "type": "string",
      "description": "Gate decision",
      "enum": [
        "allow",
        "block",
        "require_approval"
      ]
    },
    "step_id": {
      "type": "string",
      "description": "Step identifier"
    },
    "decision_id": {
      "type": "string",
      "description": "Unique decision identifier for auditing"
    },
    "reason": {
      "type": "string",
      "description": "Reason for block or approval requirement"
    },
    "policy_ids": {
      "type": "array",
      "description": "IDs of policies that matched",
      "items": {
        "type": "string"
      }
    },
    "approval_id": {
      "type": "string",
      "format": "uuid",
      "description": "Deterministic HITL queue entry UUID of the step's current hold,\npresent on a `require_approval` decision whose queue entry\nexists. A step can be held more than once: hold 1 is UUID v5 over\n`workflow_id + \":\" + step_id`, and hold n >= 2 (a step held again\nafter its earlier hold was decided) is UUID v5 over\n`workflow_id + \":\" + step_id + \"#\" + n`. The approve and reject\nresponses carry the step's current hold's id (see their\n`approval_id`). Returned by this route since #1082 but never\nspecced; added with `approval_enqueue` below,\nwhich is only meaningful alongside it. Empty when no entry was\ncreated (see `approval_enqueue`) AND on a cached replay\n(`cached: true`, the default `retry_policy: \"idempotent\"` on a\nstep that was already evaluated), which reproduces the stored\ndecision without re-running the enqueue.\n"
    },
    "approval_enqueue": {
      "type": "string",
      "enum": [
        "created",
        "reused",
        "cap_reached",
        "tier_disabled",
        "error"
      ],
      "description": "What the HITL enqueue did for this gate. Present only on a\n`require_approval` decision where an enqueue was attempted;\nomitted otherwise.\n\nA `require_approval` decision ALWAYS holds the step. This field is\nhow a client distinguishes \"held, and there is a review entry to\napprove\" (`created` / `reused`) from \"held, and there is nothing\nto approve\" (`cap_reached` / `tier_disabled` / `error`) - before\n#3408's sibling fix those were the same response.\n\n- `created` - a new queue entry was written. That includes a\n  step held AGAIN after its earlier hold was decided (approved,\n  rejected, expired or overridden): the re-hold is a new entry\n  under the next hold's `approval_id`, with its own expiry and\n  its own review, and the decided entry is kept unchanged as the\n  record of that decision.\n- `reused` - the gate resolved to the step's still-PENDING entry\n  an earlier call created. The `approval_id` is the same. Reached\n  only by a gate that is evaluated again while that entry is\n  pending (`retry_policy: \"reevaluate\"`, a gate override, or\n  concurrent gates of the step, where the gate admits them); the\n  default `retry_policy: \"idempotent\"` replays the stored\n  decision and carries `cached: true` with neither this field\n  nor `approval_id`. A gate whose entry is already decided is\n  never `reused`: it writes a new entry (`created`), or reports\n  `error` when the queue refuses (for example, the hold id names\n  an entry that belongs to another step, or the step has a queue\n  entry outside its hold ids).\n- `cap_reached` - the tenant is at its licence tier's\n  `MaxPendingApprovals`. No entry was created and none will be\n  until a pending one is resolved. **Not reachable by any shipped\n  tier**: since HITL became Enterprise-only (2026-08-26) every\n  entitled tier resolves `MaxPendingApprovals` to `-1`, and every\n  tier with a finite cap is refused by the tier gate first.\n  Documented because the mechanism is retained.\n- `tier_disabled` - the deployment's licence tier does not enable\n  HITL approvals. Entitled tiers are `Professional`, `Enterprise`\n  and `Enterprise Plus`; `Community`, `Free`, `Pro`, `Premium` and\n  `Evaluation` are refused. Approve, reject and the pending\n  listings remain reachable on a refused tier so existing entries\n  can still be drained.\n- `error` - the enqueue failed for another reason; the detail is\n  in `reason`.\n"
    },
    "approval_url": {
      "type": "string",
      "description": "URL for human approval (Enterprise)",
      "format": "uri"
    },
    "policies_evaluated": {
      "type": "array",
      "description": "All policies that were checked during evaluation (Issue",
      "items": {
        "$ref": "#/$defs/PolicyMatch"
      }
    },
    "policies_matched": {
      "type": "array",
      "description": "Policies that matched and contributed to the decision (Issue",
      "items": {
        "$ref": "#/$defs/PolicyMatch"
      }
    },
    "engine": {
      "type": "string",
      "enum": [
        "anchored"
      ],
      "description": "The engine that decided the step: `anchored`, the ADR-065 decision\nplane (PRD v11 §1.1). Omitted on a cached replay (`cached: true`),\nwhich reproduces a stored decision without deciding again.\n"
    },
    "subject_type": {
      "type": "string",
      "description": "The type of principal the step was decided for. Omitted on a\ndecision made before a subject was admitted, and wherever `engine`\nis.\n"
    },
    "policy_bundle": {
      "type": "string",
      "description": "The digest of the policy set that decided the step. Omitted\nwherever `subject_type` is.\n"
    },
    "cached": {
      "type": "boolean",
      "deprecated": true,
      "description": "**Deprecated (Issue #1673).** Whether this response was served from\na prior decision rather than a fresh policy evaluation. Use\n`retry_context.gate_count > 1` instead — `cached` conflates\nfirst-call-no vs many-retries-yes into a single bit. Kept\npopulated on every response for back-compat; removal planned\nfor a future major version.\n"
    },
    "decision_source": {
      "type": "string",
      "deprecated": true,
      "description": "**Deprecated (Issue #1673).** \"fresh\" or \"cached\". Use\n`retry_context.prior_completion_status` for the distinction\nagents and policies actually need. Kept populated on every\nresponse for back-compat; removal planned for a future major.\n",
      "enum": [
        "fresh",
        "cached"
      ]
    },
    "retry_context": {
      "$ref": "#/$defs/RetryContext"
    }
  },
  "$defs": {
    "PolicyMatch": {
      "type": "object",
      "description": "Details of a policy match during evaluation (Issue",
      "properties": {
        "policy_id": {
          "type": "string",
          "description": "Unique identifier for the policy"
        },
        "policy_name": {
          "type": "string",
          "description": "Human-readable name of the policy"
        },
        "action": {
          "type": "string",
          "description": "Action taken by this policy",
          "enum": [
            "allow",
            "block",
            "require_approval",
            "redact"
          ]
        },
        "reason": {
          "type": "string",
          "description": "Reason for the policy match"
        }
      }
    },
    "RetryContext": {
      "type": "object",
      "description": "First-class retry and execution state (Issue #1673 Phase 1). Always\npresent on every `StepGateResponse`, including the first gate call.\nReplaces the ambiguous `cached: bool` signal with unambiguous state\nthe agent and policy engine can reason about.\n",
      "required": [
        "gate_count",
        "completion_count",
        "prior_completion_status",
        "prior_output_available",
        "prior_output",
        "prior_completion_at",
        "first_attempt_at",
        "last_attempt_at",
        "last_decision",
        "idempotency_key"
      ],
      "properties": {
        "gate_count": {
          "type": "integer",
          "minimum": 1,
          "description": "Number of /gate calls for this (workflow_id, step_id), including\nthe current call. First call returns 1.\n"
        },
        "completion_count": {
          "type": "integer",
          "minimum": 0,
          "description": "Number of /complete calls for this (workflow_id, step_id). Normally\n0 on first gate, 1 after the step completes.\n"
        },
        "prior_completion_status": {
          "type": "string",
          "enum": [
            "none",
            "completed",
            "gated_not_completed"
          ],
          "description": "\"none\" on first gate call. \"completed\" when a prior /gate + /complete\nboth landed. \"gated_not_completed\" when a prior /gate landed but no\n/complete followed — uncertain territory the agent needs to reconcile\nagainst the downstream system before re-executing.\n"
        },
        "prior_output_available": {
          "type": "boolean",
          "description": "True iff prior_completion_status == \"completed\". Mirrors whether\nprior_output *could* be returned if include_prior_output=true.\n"
        },
        "prior_output": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true,
          "description": "Always present in the schema. Populated only when the caller set\n?include_prior_output=true AND prior_output_available is true.\nOtherwise null.\n"
        },
        "prior_completion_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "Timestamp of the prior /complete call, if any."
        },
        "first_attempt_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp of the first /gate call for this step. On the first call,\nequals last_attempt_at.\n"
        },
        "last_attempt_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp of this /gate call."
        },
        "last_decision": {
          "type": "string",
          "enum": [
            "allow",
            "block",
            "require_approval"
          ],
          "description": "Decision of the immediately prior /gate call. On the first call\n(gate_count == 1), equals the current decision (first-call\ninvariant).\n"
        },
        "idempotency_key": {
          "type": "string",
          "description": "The caller-supplied business-level key recorded on this step\n(Issue #1673 Phase 2). Always present in the schema — empty\nstring `\"\"` if the caller never supplied one.\n"
        }
      }
    }
  }
}

Work with this as data

Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for schemas

4 MCP tools reach this
  • find_json_schemasBrowse and filter every JSON Schema in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/axonflow-step-gate-response"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.