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_outputrejects an empty candidate;not_refuseddetects REFUSE.sources_resolverequires at least one citation and checks every named reference against a nonempty supplied input. Use[source:invoice]orSource: invoicein text, orsource,sources,cite, orcitationsfields 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_inputschecks 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_formatparses JSON objects or nonempty arrays of objects, or a rectangular Markdown table whenformatistable.required_fieldschecks the configured fields in each record. JSON is also inferred fromoutputFormat. Duplicate JSON keys, nonfinite values and numbers beyond the common safe integer range are rejected. Represent larger exact values as strings.categories_in_chartchecks the configured output field against a supplied chart array of names or objects withnameorcode. Optional coding suggestions are checked whenever present, including nested records.reconciliation_balancessums the configured input amount fields using decimal arithmetic. Both sides and the output'sleft_totalandright_totalmust 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_scorelets 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 inshadow, uses permissive capability tiers, and downgrades aggressively to cheaper models.standard: most SaaS, e-commerce, real estate, agencies, local services, and startups. Starts inenforce, uses balanced capability tiers, and keeps 90 days of audit retention.compliance: law, healthcare, dental, accounting, SOX, fintech, and regulated workflows. Starts incanary, 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 cappayment-approval: payment initiation review with a $5.00 per-call capchargeback-evidence: evidence assembly with a $1.00 per-call capagent-support: data-write support workflow with a $0.25 per-call capcode-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)
| File | Size | Uploaded | |
|---|---|---|---|
| agentguard_spend-0.16.0.tar.gz | 213.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|