Skip to main content

agentguard-spend

Local guard rules

agentguard_spend.guards is the public, local scanner used by the Hermes plugin. It exposes scan_guard_pack(tool_name, arguments, options), decision_for(scan), scan_code(code, options) and the RULES registry. Scanning does not execute the supplied command or code and makes no network calls. Results contain rule IDs and decision metadata. Keep the original arguments out of receipts and logs.

from agentguard_spend.guards import decision_for, scan_guard_pack

scan = scan_guard_pack("Bash", {"command": "git status"}, {})
decision = decision_for(scan)

The generated rule pack quotes the commands it blocks. Its data comes unchanged from the AgentGuard Codex plugin source of truth. Python matchers retain the same patterns and are checked against the Node fixtures. The Hermes plugin imports these scanners from this SDK instead of carrying a second copy. Branch-sensitive checks can inspect local Git metadata when a working directory is supplied; they never invoke Git or another shell command. An unknown branch is treated conservatively. Code that cannot be scanned completely requires approval.

Escalation ladder

The outcomes runner checks a cheap draft, then asks a different model family to correct failed checks. When two candidates exist, the stronger rung compares their final outputs against the original inputs and returns exactly A or B. Mechanical checks still decide whether an output is eligible. A preference for a failed output when the other passes requires a person. A passing draft stops without any review.

Each call starts with original inputs and final outputs only. Adapters must put only the final answer in response.text, keep provider reasoning separate, and start a fresh provider request without hidden conversation history. The optional response.reasoning field is ignored. Recognized inline reasoning tags, reasoning JSON fields, and analysis channel markers stop the ladder with final_output_required before the candidate reaches another model. Arbitrary unmarked prose cannot be reliably classified as private reasoning by this SDK.

After failed review, sensors locate the failed JSON fields, Markdown table cells, or text sections. A strong diagnosis must name those parts and their failed checks. One repair call returns replacements only for those targets. The runtime merges those replacements, preserves other JSON values or text bytes, checks the entire result, and compares A or B again. Only an unresolved repair can request a candidate from the optional escalation model, limited to the remaining diagnosed parts. Malformed formats, inconsistent inputs, missing repair locations, or a self score without field evidence require a person. Unscoped rewrites are never a fallback. The local result's repairTargets names the diagnosed parts; it is not a receipt.

The existing reviewer is the stronger model for the first comparison. Diagnosis and later comparisons use the configured escalation model when available, otherwise the reviewer. Repair uses the reviewer before optional escalation generates another patch. Operators must choose an appropriately capable escalation model from the priced registry; prices alone do not establish capability. These steps cannot be silently downgraded to another model by policy. Local-only execution uses its local reviewer for every helper and never uses the cloud escalation setting.

The additional signed roles are comparison, diagnosis, and repair. Each counts against the same cap, including diagnosis and comparison calls to the configured escalation model. A complete unresolved path makes at most eight model calls. Helper votes, diagnosis text, locations, replacement values, reasoning and candidate text stay out of receipts. The final acceptedRung identifies the producer of the accepted output, including repair, rather than the model that compared it.

Set template.checks to opt in. The vertical template adapter supplies checks for the catalog. Existing cite-or-refuse templates also use this path. Configure signing keys on the guard: without them, the ladder returns needs_person without dispatch.

Checks run locally and do not call another model:

  • nonempty_output rejects an empty candidate; not_refused detects REFUSE.
  • sources_resolve requires at least one citation and checks every named reference against a nonempty supplied input. Use [source:invoice] or Source: invoice in text, or source, sources, cite, or citations fields in JSON records. The names are input keys, not URLs to fetch. Source resolution does not establish that a statement is true or that every factual claim was cited.
  • numbers_in_inputs checks numeric literals against supplied input values. Signs, thousands separators, decimals, and scientific notation are normalized. A new total is flagged even if arithmetic could derive it; supply that total in the inputs when the output needs it.
  • structured_format parses JSON objects or nonempty arrays of objects, or a rectangular Markdown table when format is table. required_fields checks the configured fields in each record. JSON is also inferred from outputFormat. Duplicate JSON keys, nonfinite values and numbers beyond the common safe integer range are rejected. Represent larger exact values as strings.
  • categories_in_chart checks the configured output field against a supplied chart array of names or objects with name or code. Optional coding suggestions are checked whenever present, including nested records.
  • reconciliation_balances sums the configured input amount fields using decimal arithmetic. Both sides and the output's left_total and right_total must agree. Supply parsed records, not opaque document handles; missing amounts fail closed. Amounts with more than two decimal places are rejected rather than rounded.
  • model_score lets a low provider score reject a candidate. A high score cannot override a failed mechanical check.

A REFUSE goes straight to a person. A failed final check, unavailable model, cap, or provider interruption returns needs_person and names the failed checks. outputText contains only accepted output; pendingOutputText contains the candidate for human review. A capability beyond read_only, human_of_record, or outputLeavesBusiness: true always requires a person even when checks pass. Mark custom templates whose output is intended for customers or other outsiders with outputLeavesBusiness. The catalog adapter marks its outward-facing drafts. The runtime itself does not send a draft or execute a business action.

The template's maxCostCents covers the entire ladder. Each dispatch also passes through the guard's policy, including a policy downgrade. The runner must honor maxOutputTokens and report usage. An observed overrun stops further calls and remains charged in both ledgers. Failed checks do not refund incurred spend; a provider interruption retains its reservation because usage is unknown.

Escalation is unset by default. Set escalationModel on a template or override it on the execution context. An empty context string disables a template escalation. Only models with registered prices can dispatch, and origin restrictions still apply. Existing router prices also populate previously missing spend entries. Unknown model IDs never dispatch. The checked-in catalog includes further priced models that can be loaded through the existing catalog pricing sync.

localOnly: true is distinct from zero_data_plane, which describes metadata handling. Supply a separate local runner with its registered model IDs in models. The local runner must execute on your local transport and must never forward or fall back to a cloud API. The ordinary runner is never called in this mode, policy downgrades are checked again, and the last rung is always a person. Without a suitable local runner, no model is called. There is no default local installation.

Every attempted rung records check names and pass/fail in the signed decision chain, without input names, input values, output text, provider error text, or freeform verdicts. The final receipt records acceptedRung, or needs_person. The returned DAG includes the chain ancestors and settlement entries it needs for verification. Candidate text stays in the runtime result, outside the receipt.

The metadata learning helpers count dispatched rungs per template, including each comparison, diagnosis and repair call, across its last 50 checked runs. They propose start_higher when more than 25 drafts fail and stay_cheap when at least 48 pass. Proposals include manual_only and humanPromotionRequired: true; a person must promote any change. Persisting learning proposals writes a separate ladderProposals list and never changes a route.

Compatibility: ordinary templates without new fields retain their existing path and reviewer opt-in. Cite-or-refuse templates now require a resolving citation; a source word or a model score alone cannot pass them. Their reviewer output is checked too, failures require a person, and their ladder requires signing keys. Capability and outward-output handoffs also apply to older templates. The vertical adapter now adds explicit checks and requests JSON records for mechanical parsing.

from agentguard_spend.outcomes import OutcomeExecutionContext, execute_outcome_task, propose_outcome_ladder_improvements
from agentguard_spend.verticals import to_outcome_template

template = to_outcome_template('accounting', 'bank_reconciliation')
template.escalationModel = 'anthropic/claude-opus-4-7'
result = await execute_outcome_task(
    guard=guard, runner=runner, template=template, receipt_store=receipt_store,
    inputs={'statements': [{'amount': 120}], 'general_ledger': [{'amount': 120}]},
    context=OutcomeExecutionContext(scope=scope, escalationModel='claude-opus-4-6'),
)
if result['receipt'].status == 'needs_person':
    queue_for_human(result['pendingOutputText'], result['receipt'].failedChecks)
proposals = propose_outcome_ladder_improvements(await receipt_store.read_all())

Import OutcomeExecutionContext and OutcomeChecks from agentguard_spend.outcomes. Use OutcomeChecks(format='json', citations=True, numbersFromInputs=True) for a custom extraction template. Set reviewerCascadeAuto=False to stop automatic review; failed checks still require a person. For local execution, pass a local_runner whose models includes a registered ID such as openai/gpt-oss-120b, and use OutcomeExecutionContext(scope=scope, localOnly=True). The local runner's asynchronous run method must use your local server.

Functional-Use Disclaimer

DISCLAIMER: All terminology and labels used in AgentGuard’s materials are descriptive of software functionality only, not legal definitions or guarantees of compliance. For example, the terms “receipt,” “audit log,” “evidence,” “audit trail,” and “attestation” refer solely to cryptographically-signed records produced by AgentGuard’s software. These terms do not mean that any record is legally binding evidence, certified by any authority, or equivalent to records maintained by banks, auditors, or courts. Similarly, references to “signed,” “verified,” or “attested” pertain to digital signature processes, not to notarization or governmental attestation. Any use of the word “compliance,” “compliant,” “outcome,” or “settlement” describes the software’s features in a non-regulatory sense. In particular, “capability tier” is merely an internal category of agent permission levels, and does not correspond to any government or industry regulatory classification. Likewise, any statement that an operation “settles” or an outcome is “settled” refers only to the software’s final state, not to any legal settlement. No AgentGuard tool or document should be interpreted as providing legal, financial, or regulatory advice, or as a certified compliance certificate. AgentGuard is not a law firm or auditor and does not guarantee adherence to laws or standards. All use of AgentGuard software is at the user’s risk, and users must ensure independently that their use of AI agents complies with all applicable laws and regulations.* (CONTINUED IN NEXT PARAGRAPH) Throughout this documentation, package metadata, CLI banners, and related materials, any word drawn from compliance or legal contexts (such as “audit,” “evidence,” “settlement,” “credit,” “debt,” “market,” “liquidity,” “maturity,” or similar) is used only in a functional, descriptive sense. For instance, “audit log” simply means a sequence of recorded events; it does not imply an official financial or regulatory audit. The phrase “satisfies” is used to indicate that one software condition meets a programmed check (e.g. satisfying a budget cap), and is not intended to suggest that any legal requirement has been fulfilled. Under no circumstances should AgentGuard’s terminology be taken to indicate that our software is executing regulated financial or legal processes.* No term in our code, documentation, or marketing is meant to designate or characterize any AgentGuard feature as a service subject to banking, securities, derivatives, insurance, real estate, or other regulated activities. For example, “trade,” “trading,” “liquidity,” “maturity,” and similar terms (if ever used) describe algorithmic budget or token flows, not financial transactions. AgentGuard does not act as a broker-dealer, clearinghouse, insurance issuer, or government agency. References to “market” or “liquidation” are metaphorical descriptions of how the software handles tokens or budgets. No AgentGuard action should be construed as offering financial services or operating a regulated marketplace.* Likewise, words like “offer,” “obligation,” “credit,” “debt,” “payment,” or “settle” in our text refer only to hypothetical or illustrative actions of a user’s AI agent or simulated transaction flows. They do not mean that AgentGuard is engaging in any money-handling, offering financial instruments, or guaranteeing any settlement of obligations. If AgentGuard generates an invoice or cost-of-service figure, it is purely illustrative of resource usage, not a binding financial bill. The term “maker/taker” (if used in examples) is purely a naming convention and has no relation to exchange regulation.

The software’s “payment execution” tier is only a capability checkbox, not an actual payment processor. AgentGuard does not transmit money or credit.* Finally, any references to “certify,” “verify,” or “attest” should be read in context of cryptography and computing. For example, when we say a receipt is “signed” or “verified,” we mean via public-key cryptography. AgentGuard does not claim that receipts are admissible legal evidence by default. Users remain responsible for any legal implications of presenting AgentGuard logs or receipts in regulatory audits or court. This disclaimer is intended to ensure AgentGuard’s terms (in this README, license, package descriptions, CLI banner, customer agreements, and /llms.txt) make clear we provide a technical audit tool only. The functionality is delivered “as-is” with no implied regulatory endorsement.

AgentGuard proves what your AI agent attempted, who authorized it, what it cost, and whether it succeeded.

Local-runtime spend caps, capability-gated model routing, and Ed25519-signed receipts for AI agents.

Also available in: Español (LATAM) · Português (BR)

Every policy decision runs inside your process. Prompts, completions, provider API keys, signing keys, policies, and cost overrides never go to AgentGuard infrastructure. OpenRouter calls go directly from your runtime to openrouter.ai with your key.

Quickstart in 90 seconds

pip install agentguard-spend
agentguard auth openrouter
agentguard wizard

The wizard writes:

  • ~/.agentguard/policy.yaml
  • ~/.agentguard/quickstart.ts
  • ~/.agentguard/quickstart.py

It also prints the snippet to paste into your app:

const response = await guardedClient.chat.completions.create({
  model: 'openai/gpt-4o-mini',
  messages: [{ role: 'user', content: 'Run the governed task.' }],
});

Then run your agent. AgentGuard decides locally before any provider call starts, signs the receipt, and applies allow, downgrade, shadow, or block.

Workflow-level caps

Use agentguard_spend.workflow() when one agent run spans many outcomes and needs one shared budget envelope. The SDK signs each step as receipt schema v2, writes checkpoints, and validates the prior chain before resume.

from agentguard_spend import WorkflowConfig, workflow

async with workflow(WorkflowConfig(
    name='migrate_legacy_payments',
    budget_cap_usd=500,
    duration_cap_hours=72,
    checkpoint_every_outcomes=50,
    resume_if_exists=True,
)) as wf:
    for record in records:
        await wf.outcome('migrate_payment', lambda: migrate_payment(record))

Share the public replay URL at https://agentguard.run/verify/workflow/<workflow_id>.

Need help configuring? Run agentguard advisor

agentguard advisor uses your OpenRouter key, or any OpenAI-compatible endpoint you pass with --base-url, to run a local setup dialogue in your terminal. AgentGuard infrastructure never sees the prompts, completions, keys, policy details, or session log.

agentguard advisor

Advisor writes ~/.agentguard/policy.yaml, a language-aware quickstart file, projected savings math, and a local JSONL session log under ~/.agentguard/advisor-sessions/.

Governance Posture

Advisor asks for one operating-style input and uses it to shape the generated policy.

  • velocity: high-ship software and AI teams. Starts in shadow, uses permissive capability tiers, and downgrades aggressively to cheaper models.
  • standard: most SaaS, e-commerce, real estate, agencies, local services, and startups. Starts in enforce, uses balanced capability tiers, and keeps 90 days of audit retention.
  • compliance: law, healthcare, dental, accounting, SOX, fintech, and regulated workflows. Starts in canary, requires stricter capability tiers, blocks regulated overflow instead of downgrading, and keeps 7 years of audit retention.

Override the suggestion when you already know how the team operates:

agentguard advisor --posture velocity
agentguard advisor --posture compliance

custom posture is reserved for the Solo tier Outcome Builder.

Why OpenRouter?

One OpenRouter key gives your team access to hundreds of models across many providers. Your CFO sees one invoice. AgentGuard enforces who uses what, which task tiers can reach which models, and what each call can spend. The OpenRouter key can live in OPENROUTER_API_KEY or ~/.agentguard/openrouter-key with mode 600.

Sync pricing when you want local cost math refreshed:

agentguard models --sync-pricing
agentguard models --task payment-approval
agentguard models --search gpt-4o --json

Pricing overrides are stored locally in ~/.agentguard/cost-overrides.json.

Verify any receipt

Share https://agentguard.run/verify with an auditor or reviewer. Paste a receipt and public key in the browser to verify the Ed25519 signature, entry hash, and chain link. The receipt never leaves the page.

CLI verification is still local:

agentguard demo
agentguard verify --trace latest

Task templates

agentguard wizard ships templates for:

  • risk-review: read-only review with a $0.50 per-call cap
  • payment-approval: payment initiation review with a $5.00 per-call cap
  • chargeback-evidence: evidence assembly with a $1.00 per-call cap
  • agent-support: data-write support workflow with a $0.25 per-call cap
  • code-scan: long-context read-only scan with a $0.10 per-call cap

Each template sets recommended OpenRouter model assignments, capability tier, fallback model, caps, and system instructions.

Provider bindings

TypeScript includes native OpenAI, Anthropic, and Bedrock bindings. Streaming usage is settled from provider usage events when available, with local token-estimator fallback when usage is missing. Settlement entries are signed into the same hash chain as enforcement decisions.

Python includes OpenAI, Anthropic, Bedrock, LangChain, CrewAI, and LlamaIndex integration helpers.

No proxy

AgentGuard Spend is a library, not a gateway. It does not proxy traffic, store prompts, hold provider keys, or host policy state. The signed log lives in your storage.

Telemetry

Telemetry is opt-in. Set AGENTGUARD_TELEMETRY=1 or run agentguard telemetry enable. The beacon sends only SDK version, runtime, OS family, anonymous install ID, CI flag, TTY flag, and event name. No prompts, completions, provider keys, signing keys, policy details, or cost overrides are sent.

License and usage thresholds

The SDK is free for evaluation, prototyping, non-commercial development, and production deployments processing up to 10,000 enforcement calls per calendar month. Commercial use above that threshold requires a paid license from Dunecrest Ventures Inc. Full terms are in LICENSE.

Patent notice

Certain AgentGuard technologies are patent pending in the United States.

Metadata

Release files for agentguard-spend 0.16.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentguard-spend 0.16.0
File Size Uploaded
agentguard_spend-0.16.0.tar.gz 213.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agentguard-spend 0.16.0
File Interpreter ABI Platform
agentguard_spend-0.16.0-py3-none-any.whl Python 3 none any Details

Total release size: 471.7 kB

Release files / agentguard_spend-0.16.0.tar.gz

Download URL agentguard_spend-0.16.0.tar.gz
Size 213.0 kB
Tags Source
SHA-256 checksum
How to use checksums
2f32a64c241b2ac7cf8acc7a80de3ed0733d8cd5b691cbad4427f1f06cf81ba3
BLAKE2b-256 checksum
How to use checksums
66ce3ea3c9731d43c6ced521b63951d1dfd00b1071b10df7440d6258cd28b4a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / agentguard_spend-0.16.0-py3-none-any.whl

Download URL agentguard_spend-0.16.0-py3-none-any.whl
Size 258.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e96cf26cac1979d691aa8aff06f9e99c247f5ca6d2eb99631787834bfe57fffa
BLAKE2b-256 checksum
How to use checksums
b6f3fe4dcd0f7f17c705dc202db28a00aa84499b0140c2b342e193021385a955
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.8 {"installer":{"name":"uv","version":"0.12.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.16.0 This release

2 release files

0.15.4

2 release files

0.15.3

2 release files

0.15.2

2 release files

0.15.1

2 release files

0.15.0

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.3

2 release files

0.13.2

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.10

1 release file

0.1.9

1 release file

0.1.8

1 release file

0.1.7

1 release file

0.1.6

1 release file

0.1.5

1 release file

0.1.4

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page