cayu.approvals.business
Public Cayu API. Definitions are grouped by their public source module, and definitions from private implementation modules appear on their package’s page; adding a symbol does not move existing links. The import shown at each entry is a supported public namespace. Read the Python API overview and install the required extra.
business_approval_audit
Section titled “business_approval_audit”from cayu.approvals import business_approval_auditProject approval events into business approval records.
Pass the output of session_store.load_events(...) or an
EventQuery filtered to the approval event types — in any order and
from any number of sessions (records pair per session; requests are
seeded before resolutions are applied). Parsing is lenient: approvals
paused without the routing carrier project with routing=None, and
unstamped resolutions (made through the raw primitive) project with
outcome=None — the audit never raises on foreign approvals. The
projection records what callers asserted; it does not authenticate the
stamp — a caller at operator trust level resolving through the raw
primitive can write any resolution metadata, including this stamp.
business_approval_audit(events: Iterable[Event]) -> list[BusinessApprovalRecord]Release source · Runtime guarantees · Capability guides
BUSINESS_APPROVAL_RESOLUTION_METADATA_KEY
Section titled “BUSINESS_APPROVAL_RESOLUTION_METADATA_KEY”from cayu.approvals import BUSINESS_APPROVAL_RESOLUTION_METADATA_KEYBUSINESS_APPROVAL_RESOLUTION_METADATA_KEY = approval_support.BUSINESS_APPROVAL_RESOLUTION_METADATA_KEYRelease source · Runtime guarantees · Capability guides
business_approval_routing
Section titled “business_approval_routing”from cayu.approvals import business_approval_routingRead the routing carrier off a pending approval.
Raises BusinessApprovalRoutingMissing when the pause was created
without the carrier or the carrier is malformed — the tier gate never
silently degrades into an ungated resolve.
business_approval_routing(pending: PendingToolApproval | PendingToolApprovalEventView) -> BusinessApprovalRoutingRelease source · Runtime guarantees · Capability guides
business_approval_routing_metadata
Section titled “business_approval_routing_metadata”from cayu.approvals import business_approval_routing_metadataBuild the ToolPolicyResult.metadata carrier for a routed approval.
Merge the returned dict into the metadata of a
ToolPolicyResult(decision=REQUIRE_APPROVAL, ...); the routing then
persists on the pending approval and surfaces to approval UIs in the
tool.call.approval_requested event under
payload["approval"]["metadata"].
business_approval_routing_metadata(*, required_tier: str, chain: Sequence[str], metadata: Mapping[str, Any] | None=None) -> dict[str, Any]Release source · Runtime guarantees · Capability guides
BUSINESS_APPROVAL_ROUTING_METADATA_KEY
Section titled “BUSINESS_APPROVAL_ROUTING_METADATA_KEY”from cayu.approvals import BUSINESS_APPROVAL_ROUTING_METADATA_KEYBUSINESS_APPROVAL_ROUTING_METADATA_KEY = 'cayu:business_approval_routing'Release source · Runtime guarantees · Capability guides
BusinessApprovalError
Section titled “BusinessApprovalError”from cayu.approvals import BusinessApprovalErrorBase class for business-approval adapter failures.
Bases: Exception.
This type’s implementation and inherited behavior are available in the linked release source.
Release source · Runtime guarantees · Capability guides
BusinessApprovalOutcome
Section titled “BusinessApprovalOutcome”from cayu.approvals import BusinessApprovalOutcomeBases: StrEnum.
Fields and attributes
Section titled “Fields and attributes”Defaults below are source expressions; Field(...) includes schema/validation settings and default_factory creates a fresh value. Inherited declarations are included. Constructor behavior follows the model or dataclass shown in the bases/decorators.
| Name | Type | Default |
|---|---|---|
APPROVED |
class attribute |
'approved' |
CONDITIONED |
class attribute |
'conditioned' |
DECLINED |
class attribute |
'declined' |
Release source · Runtime guarantees · Capability guides
BusinessApprovalRecord
Section titled “BusinessApprovalRecord”from cayu.approvals import BusinessApprovalRecordOne business approval, projected from the session’s approval events.
resolution_state distinguishes a pending request, a binary runtime
decision, and a non-authorizing recovery acknowledgement. decision is
the raw Cayu decision (None while pending or safely blocked);
outcome is the business outcome stamped by the adapter (None while
pending, and None on unstamped resolutions made through the raw
primitive). resolved_by is the typed ResolutionActor provenance
the runtime stamped on the resolution event, when the resolver supplied
one — the authenticated who/how next to the caller-asserted
approver_id/approver_tier. expired is True when the runtime’s
approval TTL closed on the attempt and coerced it to a denial: the
stamped business fields then record what the approver asserted, while
decision records the expiry-coerced outcome (so decision=DENY
with outcome=approved reads as “approved too late”).
Decorators: @dataclass(frozen=True).
Fields and attributes
Section titled “Fields and attributes”Defaults below are source expressions; Field(...) includes schema/validation settings and default_factory creates a fresh value. Inherited declarations are included. Constructor behavior follows the model or dataclass shown in the bases/decorators.
| Name | Type | Default |
|---|---|---|
approval_id |
str |
required |
session_id |
str |
required |
tool_call_id |
str |
required |
tool_name |
str |
required |
agent_name |
str |
required |
routing |
BusinessApprovalRouting | None |
required |
resolution_state |
BusinessApprovalResolutionState |
required |
decision |
ToolApprovalDecision | None |
required |
outcome |
BusinessApprovalOutcome | None |
required |
condition_text |
str | None |
required |
approver_id |
str | None |
required |
approver_tier |
str | None |
required |
resolved_by |
ResolutionActor | None |
required |
reason |
str | None |
required |
expired |
bool |
required |
requested_at |
datetime | None |
required |
resolved_at |
datetime | None |
required |
pending (property)
Section titled “pending (property)”BusinessApprovalRecord.pending() -> boolresolved_via_adapter (property)
Section titled “resolved_via_adapter (property)”BusinessApprovalRecord.resolved_via_adapter() -> boolRelease source · Runtime guarantees · Capability guides
BusinessApprovalResolutionState
Section titled “BusinessApprovalResolutionState”from cayu.approvals import BusinessApprovalResolutionStateDurable lifecycle state of one business approval.
Bases: StrEnum.
Fields and attributes
Section titled “Fields and attributes”Defaults below are source expressions; Field(...) includes schema/validation settings and default_factory creates a fresh value. Inherited declarations are included. Constructor behavior follows the model or dataclass shown in the bases/decorators.
| Name | Type | Default |
|---|---|---|
PENDING |
class attribute |
'pending' |
APPROVED |
class attribute |
'approved' |
DENIED |
class attribute |
'denied' |
BLOCKED |
class attribute |
'blocked' |
Release source · Runtime guarantees · Capability guides
BusinessApprovalRouting
Section titled “BusinessApprovalRouting”from cayu.approvals import BusinessApprovalRoutingProduct-computed routing for one business approval.
chain is ordered lowest to highest authority; required_tier is the
minimum tier that may resolve. metadata carries product extras (package
id, amount, cost center, …) for the approval UI and the audit trail.
Bases: BaseModel.
Fields and attributes
Section titled “Fields and attributes”Defaults below are source expressions; Field(...) includes schema/validation settings and default_factory creates a fresh value. Inherited declarations are included. Constructor behavior follows the model or dataclass shown in the bases/decorators.
| Name | Type | Default |
|---|---|---|
kind |
str |
BUSINESS_APPROVAL_ROUTING_KIND |
required_tier |
str |
required |
chain |
tuple[str, ...] |
required |
metadata |
dict[str, Any] |
Field(default_factory=dict) |
validate_kind (method)
Section titled “validate_kind (method)”BusinessApprovalRouting.validate_kind(value: str) -> strvalidate_required_tier (method)
Section titled “validate_required_tier (method)”BusinessApprovalRouting.validate_required_tier(value: str) -> strvalidate_chain (method)
Section titled “validate_chain (method)”BusinessApprovalRouting.validate_chain(value: Any) -> tuple[str, ...]copy_metadata (method)
Section titled “copy_metadata (method)”BusinessApprovalRouting.copy_metadata(value: Any) -> dict[str, Any]validate_required_tier_in_chain (method)
Section titled “validate_required_tier_in_chain (method)”BusinessApprovalRouting.validate_required_tier_in_chain() -> BusinessApprovalRoutingRelease source · Runtime guarantees · Capability guides
BusinessApprovalRoutingMissing
Section titled “BusinessApprovalRoutingMissing”from cayu.approvals import BusinessApprovalRoutingMissingThe pending approval carries no (valid) business-approval routing.
Raised when a pause was created without business_approval_routing_metadata
(for example by a plain policy) or the carrier payload is malformed. The
adapter refuses rather than resolving ungated — resolve such approvals with
CayuApp.resolve_tool_approval directly.
Bases: BusinessApprovalError.
This type’s implementation and inherited behavior are available in the linked release source.
Release source · Runtime guarantees · Capability guides
BusinessApprovalTierMismatch
Section titled “BusinessApprovalTierMismatch”from cayu.approvals import BusinessApprovalTierMismatchThe asserted approver tier may not resolve this approval.
Bases: BusinessApprovalError.
init (method)
Section titled “init (method)”BusinessApprovalTierMismatch.__init__(*, approver_tier: str, required_tier: str, chain: tuple[str, ...]) -> NoneRelease source · Runtime guarantees · Capability guides
resolve_business_approval
Section titled “resolve_business_approval”from cayu.approvals import resolve_business_approvalResolve a routed business approval and return the resumed event stream.
Enforces the tier gate against the routing persisted on the session’s
pending-approval checkpoint — never a caller-supplied value —
(approver_tier must sit at or above required_tier in the
ordered chain), maps the business outcome onto the binary primitive
(APPROVED/CONDITIONED resume as approve — CONDITIONED requires
condition_text; DECLINED resumes as deny), stamps the business
outcome into the resolution metadata for the audit trail, and delegates to
CayuApp.resolve_tool_approval.
This is a coroutine returning the event iterator: gate failures raise at
await time, before any event is consumed —
events = await resolve_business_approval(...) then iterate. The
approved tool sees the stamped record via
ToolContext.metadata["cayu:business_approval"]; the model does not see
approve-path metadata, so a condition that must steer the model has to be
surfaced by the tool’s own result. The gate is an application affordance,
not a security boundary: approver_id/approver_tier are
caller-asserted, and direct primitive callers bypass the adapter entirely
(unstamped resolutions show outcome=None in the audit; a same-trust
caller can also forge the stamp — authenticate approvers product-side and
pass resolved_by (a ResolutionActor from your auth layer) so the
typed provenance the runtime stamps sits next to the business assertion).
The primitive independently reloads and re-validates the pending approval
when the returned stream is first iterated, so a resolution race lost
after this gate surfaces as the primitive’s own status-conflict error.
Approval expiry composes the same way: a tier-authorized resolution whose
approval window already closed is coerced by the runtime to a denial —
no typed error; the stream carries tool.call.approval_expired and
denial events with expired: true, and the audit record shows
expired=True next to the asserted outcome.
async resolve_business_approval(app: CayuApp, *, session_id: str, task_worker_id: str | None=None, approval_id: str, approver_id: str, approver_tier: str, outcome: BusinessApprovalOutcome | str, condition_text: str | None=None, reason: str | None=None, metadata: dict[str, Any] | None=None, resolved_by: ResolutionActor | None=None, max_steps: int | None=None, limits: RunLimits | None=None, budget_limits: tuple[BudgetLimit, ...] | None=None, retry_policy: RetryPolicy | None=None, structured_output: StructuredOutputSpec | None=None, thinking: ThinkingConfig | None=None, loop_policies: tuple[LoopPolicy, ...]=()) -> AsyncIterator[Event]Release source · Runtime guarantees · Capability guides
TieredApprovalPolicy
Section titled “TieredApprovalPolicy”from cayu.approvals import TieredApprovalPolicyPause tool calls for business approval with a product-computed routing.
Tier computation stays product-owned: compute_routing receives the
ToolPolicyRequest and returns a BusinessApprovalRouting (pause for
approval at that tier) or None (allow without approval). The callback
may be sync or async — a product implementation typically consults its own
rules or database. It can run more than once for the same call: the
runtime re-authorizes when a before_tool_call hook modifies arguments
(marked with request.metadata[TOOL_POLICY_REAUTHORIZATION_METADATA_KEY]),
so keep the callback deterministic and side-effect free; a
REQUIRE_APPROVAL verdict on re-authorized arguments blocks the call
instead of pausing again. expires_in_seconds bounds how long the
resulting approval demand stays valid, exactly like
AlwaysRequireApprovalToolPolicy(expires_in_seconds=...).
Bases: ToolPolicy.
execution_profile_identity (property)
Section titled “execution_profile_identity (property)”TieredApprovalPolicy.execution_profile_identity() -> ExecutionProfileBehaviorIdentity | NoneReturn a stable application declaration, or None when non-portable.
authorize (method)
Section titled “authorize (method)”async TieredApprovalPolicy.authorize(request: ToolPolicyRequest) -> ToolPolicyResultinit (method)
Section titled “init (method)”TieredApprovalPolicy.__init__(*, compute_routing: Callable[[ToolPolicyRequest], BusinessApprovalRouting | None | Awaitable[BusinessApprovalRouting | None]], reason: str | None=None, expires_in_seconds: float | None=None) -> None