Skip to content

guard()

The primary method for gating a risky action. Runs a preflight check against your policy and executes the action only if allowed.

python
client = gavrun.get_client()

result = client.guard(
    action="send_email",
    execute=lambda: send_email(to, subject, body),
    tools=["send_email"],
    prompt=f"Send email to {to}: {subject}",
)

Signature

python
def guard(
    self,
    *,
    action: str,
    execute: Callable[[], Any],
    target: str | None = None,
    context: dict[str, Any] | None = None,
    prompt: str | None = None,
    agent_id: str | None = None,
    request_id: str | None = None,
    session_id: str | None = None,
    user_id: str | None = None,
    user_role: str | None = None,
    tools: list[str] | None = None,
    models: list[str] | None = None,
    max_tokens: int = 1000,
    environment: str | None = None,
    context_labels: list[str] | None = None,
    steps: list[dict[str, str]] | None = None,
    attachments: list[dict[str, Any]] | None = None,
    resume_decision_id: str | None = None,
    resume_approval_id: str | None = None,
    resume_request_id: str | None = None,
) -> GuardResult

Parameters

ParameterTypeDescription
actionstrName of the action being guarded (e.g. "delete_user"). Used as the tool name in the policy check.
executeCallable[[], Any]Zero-argument callable that performs the action. Called only on allow.
targetstrWhat the action targets (e.g. "user_database"). Used to build the prompt.
contextdictAdditional context dict included in the audit record.
promptstrPlain-English description of the action. Auto-generated from action/target/context if omitted.
session_idstrGroups related tool calls in the audit log and quota tracking.
user_idstrThe end user triggering the action.
user_rolestrRole of the user (e.g. "admin", "operator").
toolslist[str]Tools being used. Defaults to [action].
modelslist[str]Models in use for this request.
max_tokensintEstimated token budget. Default 1000.
attachmentslist[dict]Arbitrary data shown to human reviewers in the approval queue.
resume_*strResume a previously paused human-review decision.

Returns

GuardResult

Outcomes

python
result = client.guard(action="delete_user", execute=lambda: delete_user(id), tools=["delete_user"])

if result.executed:
    # Policy allowed it — execute() was called, result.result holds the return value
    print(result.result)

elif result.requires_human_review:
    # Paused — poll for approval
    approval_id = result.decision.get("approval_id")
    while True:
        status = client.get_approval_status(approval_id=approval_id)
        if status["status"] == "approved":
            # Re-run with resume
            result = client.guard(
                action="delete_user",
                execute=lambda: delete_user(id),
                tools=["delete_user"],
                resume_approval_id=approval_id,
            )
            break
        elif status["status"] == "denied":
            raise PermissionError("Denied by reviewer")
        time.sleep(3)

elif result.denied:
    raise PermissionError("Blocked by policy")

Deferred execution

Pass execute=lambda: None when you want to control execution yourself after the preflight:

python
result = client.guard(
    action="refund_order",
    execute=lambda: None,   # deferred
    tools=["refund_order"],
    prompt=f"Refund order {order_id}",
)

if not result.denied and not result.requires_human_review:
    actual_result = process_refund(order_id)

Apache 2.0 License