Allowit: A Policy Engine for Delegated Work

Abstract

Allowit is a policy engine for work that agents do on an owner's behalf. It turns the owner's stated purpose into policy source, typed parameters and recorded state, all of which the owner can review.

Owners define the rules. Agents propose operations, which are checked in two places:

  1. The server gathers data from the marketplace, the web and models.
  2. A smart contract checks chain-native operations that the server authorized.

When the owner answers an uncertain question, the answer informs later uses of the same question. After review, it can also train specialist models offline. In this paper we look at several sample Stellar treasury Allowit policies to show how evaluation, recovery, cost accounting and organizational use work.

An agent that can search for services, pay for them and change a financial position can move work forward between an owner's decisions. Each of those steps commits something: money, a counterparty, a disclosure or a position. An agent can stay under its budget and still buy irrelevant stuff; that's exactly why we're building Allowit. Our research focuses on solving alignment of enforceable intent between owners and their agents.

Allowit records the owner's purpose as a policy and checks each operation against it at the point of execution. The owner reviews the policy’s source and parameters before installation, then uses the allowit CLI, SDK, authoring agent, or web app to configure and fund their agent’s wallets. They retain control at all times and can unilaterally close or drain their agent’s wallets. We explain below how this works.

x402

Delegation and executable authority

An agent may encounter a new supplier or a changed position after its owner assigns the work. The owner cannot review every future instruction in advance. Delegation therefore needs rules that apply when the agent acts. Saltzer and Schroeder’s 1975 account of computer protection established two relevant principles: grant only the privileges a task needs, and check authority on every access.

OAuth 2.0, published in 2012, gives clients limited access through scoped, time-bounded authorization. The application still decides what that scope means for a particular action.

The 2014 Ethereum white paper describes executable state transitions. A policy wallet uses this structure to check asset, destination, amount and replay state as part of the transaction. The ledger enforces those conditions independently of the software proposing the operation.

x402 connects payment to service access: a server supplies payment requirements through HTTP 402, and the client retries with payment authorization. Allowit combines service discovery with policy evaluation around that exchange.

Component responsibilities

A limit set by an owner may appear in an editor, in the server's check before signing and in a contract's check during invocation. If each place kept its own copy of the rule, those checks could drift apart. The architecture gives them shared definitions while keeping evidence gathering, signing authority and native enforcement in the components responsible for those functions.

Owner interface

Micro Ownerowner mechanismSourceParametersOwner review

The app, CLI and policy-authoring agent let the owner state intent in natural language. Then delegates policy generation and presents results: the policy source code and editable typed parameters.

Evaluation

Micro Evaluationevaluation mechanismCLIServerlocal signerprivate evidenceShared SDK evaluatorSource · params · request · stateDecision · journal

SDK core defines common types, rules and primitives. The SDK engine supplies shared execution logic to the CLI and server, so a rule such as daily_volume_limit retains one meaning across those surfaces.

Enforcement

Micro Enforcementenforcement mechanismExternalharnessServerdelegated authorityRail

Vendor packages bind assets and operations to exact native identities, contracts and signing semantics. The server authorizes an exact action using private context; the rail verifies the required signatures, policy identity, replay state, installed constraints, and observable asset effects.

Allowit provides a modular system of Rust and NPM packages that allow scalable extensibility across rails, models, and business needs.

For starter, we have: marketplace retrieval, web evidence, report fetching and model assessment implemented server-side with SQL storage, vector search, and split credentials. The result of running any of the supported policy functions reaches the ledger of a supported rail for contract enforcement. We illustrate here the high level architectural diagram of the system.

Canonical MergedComponent responsibilities and relationships. The external execution harness can use the CLI, call the optional policy-authoring agent and exchange requests or skill instructions with the server.A2AnpmA2UInpmnpmcratecratecratecratecrate + npmRESTRESTRESTACPSKILL.mdRESTallowit-engine./agentADK appPolicy authoringallowit-enginecrate @allowit/agentACP / A2A AgentPolicy authoringapp.allowit.xyznpm @allowit/appdapp walletsallowit-sdkcrate @allowit/cliDX: policy and agent keypairgenerationPolicy validation · x402 marketplaceallowit-enginecrate @allowit/serverShared REST API · server enforcementSQLite / PostgreSQLUser storageMarketplace storageVector DBallowit-enginenpm @allowit/uiShared policy webcomponentsallowit-sdkcrate @allowit/sdk/engineAll other shared logiccrate + npm @allowit/vendor/*Native contracts · signing · chainsemanticsSVG graphics · web componentsallowit-corecrate + npm @allowit/sdk/coreCommon types · policy rules · primitivesTypeScript interfacesExternal agent harnessClaude · Codex · Antigravity · customClient-controlled key storage

Onboarding interfaces

To make our system useful, we needed a user interface. Since we expect various groups of human users and agents to generate policies at different times, we decided to provide 3 main entry UI points. The web app, authoring agent (available over A2A and ACP interfaces) and the allowit CLI are 3 alternative for generating, reviewing and deploying policy artifacts. Execution can continue through an external agent harness after the owner installs the mandate.

Web app

A browser interface for entering intent, editing source and parameters, and reviewing the policy before owner signing.

ACP / A2A Agent

Our policy-authoring agent drafts and revises policies. Other agents can call it as a tool when they need authoring help.

CLI

A local interface for policy generation, validation, parameter editing and deployment. The executing harness can also use its commands.

Installation and revision

Installation turns a reviewed policy into standing authority. The owner reviews source, effective parameters, target network and enforcement placement, then signs the native installation. Verification compares the installed executable and configuration with that approval; funding is separate.

The CLI checks admitted source and types, then emits source for native compilation (SDK policy template). Parameter revisions preserve usage and replay history. An off-chain source edit requires a new owner binding; changing enforced Custom source requires a matching compiled executable. Changing an enforced canonical prefix likewise changes the approved enforcement binding, even when its checks use shared rules. The contract records the authored source’s SHA-256 (custom-policy).

The owner signs a deployment packet with the next consecutive configuration version. If ownership changes, the new owner also signs. The packet replaces configuration while preserving policy state and request nonce. Unchanged code validates configuration at update; replacement code validates its rules on its next call, with the owner binding the exact executable hash (policy-wallet).

Subsequent actions bind the current revision. Already-submitted transactions retain their original identity for reconciliation.

Authority LifecycleOwner review and signing install authority. An exact request is evaluated. Denial stops. An owner answer resumes the paused rule and reaches final checks and admission. Only admitted requests are signed, persisted and submitted.Policy installationValidate policyOwner reviewand signingDeployVerifyactive policyOperation authorizationExact requestauthenticated factsPolicyevaluationdenyStopno executionaskOwner questionscoped answerOwner denial stopsResume paused rulewith scoped answerallowFinal checksand admissionPersist signed bytesSubmit exact operation

A treasury policy

Consider an organization whose payroll and supplier invoices fall due in one settlement asset, while part of its reserves sits in an owner-approved vault. Its obligation schedule determines how much cash must be available and when. The delegated task is to maintain that availability and respond to material risk in the existing position. ENS’s investment policy similarly links treasury management to operating obligations and capital preservation.

The first policy example allows an agent to research the marketplace and, before paying, decide whether the report answers the right question. It is also instructed to use sane limits and escalate to a human if unsure.

Read the permitted operation from the authenticated request and load the owner’s public-search query. Clearing opens a new evidence window.

For a report payment, read the owner’s catalog query, search the marketplace and select the report-purchase question. For a redemption or swap, fetch the report from the configured URL, verify the response with the configured public key and select the position-review question. Any other operation ends the evaluation with an error.

Both branches collect public corroboration before a System One model assesses the ordered evidence. Read the selected question and its two thresholds from the owner’s parameters. Check that the deny threshold does not exceed the allow threshold and that both fit the 10,000-point scale.

Submit the question and thresholds to System One. A score below deny_below denies. A score at or above allow_above passes. Anything in between goes to the owner. Widening the band between them sends more decisions to the owner for feedback, and narrowing it delegates more to the classifier. An accepted assessment lets the host policy return success.

The server records each search or fetch in order, including its source and observation time when available. Each assessment records the model identity, question identity, thresholds and assessed request. An owner correction is stored against that classifier and request.

After a successful host evaluation, the server signs the prepared native request. The contract checks the authorized native operation and its observable effects.

Evidence calls inside execute
Call configurationInput and result
AllowitMarketplaceSearchquery: the owner-scoped service requirement; returns candidate service data with provider identity and source.
AllowitInternetSearchquery: public corroboration question; returns sourced search evidence rather than an executable instruction.
AllowitFetchmethod, URL, request data and verification key identify the expected report response.
AllowitSystemOneid, query, deny_below and allow_above identify the classifier and its decision thresholds. Thresholds use integer basis points on the returned score; they are policy settings, not measured accuracy.

Host policy

use allowit::prelude::*;
use allowit::{AllowitFetch, AllowitInternetSearch, AllowitMarketplaceSearch, AllowitSystemOne};

/// Find reports about my vault in the marketplace and check public sources.
/// Before paying, decide whether the report answers my question.
/// Before taking money out or swapping, read the report and check the latest facts.
/// Use my limits and ask me when you are unsure.
pub fn execute(ctx: &AllowitContext) -> allowit::Result {
    let operation = allowit::operations(ctx, &ctx.params[allowit::OPERATIONS].ok())?;
    let web_query: String = ctx.params["web_query"].ok();
    allowit::clear_systemone_context(ctx)?;

    let id = match operation {
        "transfer" => {
            let catalog_query: String = ctx.params["catalog_query"].ok();
            allowit::marketplace_search(
                ctx,
                &AllowitMarketplaceSearch {
                    query: &catalog_query,
                },
            )?;
            "report_purchase"
        }
        "redeem" | "swap" => {
            let url: String = ctx.params["report_url"].ok();
            let key: String = ctx.params["report_key"].ok();
            allowit::fetch(
                ctx,
                &AllowitFetch {
                    method: "GET",
                    url: &url,
                    data: "",
                    pubkey: &key,
                },
            )?;
            "position_review"
        }
        _ => return Err(AllowitError::OperationNotAllowed),
    };
    allowit::internet_search(ctx, &AllowitInternetSearch { query: &web_query })?;
    let question: String = ctx.params[id].ok();
    let deny_below: u32 = ctx.params["deny_below"].ok();
    let allow_above: u32 = ctx.params["allow_above"].ok();
    assert!(deny_below <= allow_above && allow_above <= 10_000);
    allowit::systemone(
        ctx,
        &AllowitSystemOne {
            id: id,
            query: &question,
            deny_below: deny_below,
            allow_above: allow_above,
        },
    )?;
    Ok(())
}

Policy representation

An owner who raises a spending ceiling should not have to rewrite the logic that decides which operations are allowed. The engine judging a new request also needs to know how much of that ceiling earlier operations have already used. Allowit therefore represents a policy as three parts: source that orders the checks, owner parameters that hold editable limits and allowed values, and state that records accumulated usage. All three are evaluated against authenticated facts about the operation actually being performed, which are kept apart from the arguments used to build it.

Source

let remaining =
 allowit::daily_volume_limit(
  ctx,
  &ctx.params[
   allowit::DAILY_VOLUME_LIMIT
  ].ok(),
 )?;

The source sets the order of checks and holds custom decision logic. Only rules called by this source impose business constraints; storing a limit alone does not activate it.

Owner parameters

Micro Paramsparams mechanismExample owner choicesreport_limit$25 USDCswap_limit$1,000reserved_volume$200

Here, $ amounts denote USDC units. Parameters hold editable limits and allowed values. The owner can change a report limit or retained-capacity requirement without changing the decision logic. Existing usage remains recorded.

State

Instance key 0 · AllowitState
nonce: u647
deployment_version: u642
policy_state
callsInt(7)
day_totalInt(1_200_000_000)
Example values · partial storage view

State records prior use. Rules read pre-operation state. Successful execution commits staged usage and nonce updates with the native effects.

These objects come together in one structure, AllowitContext, whose fields are env, params, state and request. The environment identifies the backend and the facilities it supports. Common rule functions read from this context. Each returns either an error or the constraint it established, such as the capacity left under a limit or the destination that matched an allowed set. A rule's result is an input to the policy, and the policy decides how results combine into a decision. For example in the treasury mandate, the native policy stores the capacity returned by daily_volume_limit and later compares it with an owner reserve.

Wallet forms and policy placement
Wallet / placementEnforcementPublic source
Native / classic Classic multisignature account · G…Native signer thresholds; business policy evaluated by the server. Owner weight 3, agent and server weight 1 each; low/medium/high thresholds 2/2/3. No authored contract code.Classic wallet setup
Simple AllowitSimplePolicyEngine · C…Server evaluates canonical-only source; contract enforces custody and authorization invariants.Simple wallet contract
Common AllowitCommonPolicyEngine · C…Contract enforces the owner-approved ordered canonical prefix.Common wallet contract
Custom AllowitCustomPolicy · C…Authored deterministic source compiles into the wallet contract.Custom wallet contract

Stellar Testnet workflow

Author and review

Select Stellar Testnet and generate a treasury draft. The owner names the approved asset, seller, vault and exchange, then sets the spending limits, reserve, share cap and minimum outputs in native units. The draft contains the host evidence policy, the native custody policy and their typed parameters. The two policy files each expose execute(ctx).

allowit rail use stellar:testnet
allowit policy generate --owner-key owner --origin "$ORIGIN" \
  --profile allowit-stellar-custom-wallet-v1 --new-wallet --out treasury \
  "Maintain USDC for payroll. Buy vault evidence from $SELLER, redeem approved vault $VAULT and convert through $ROUTER within the installed limits."
allowit policy edit treasury
allowit policy check treasury/host.rs
allowit policy check treasury/native.rs

Build and install

In the Stellar contracts checkout, emit the checked native source into the Custom wallet crate and compile it to Wasm. The owner reviews the target network, asset, authorities, source and executable hashes, typed parameters and estimated fees. The owner signs the installation through their local signer.

allowit policy build treasury/native.rs -o crates/custom-policy/policy/policy.rs
stellar contract build --locked --package allowit-custom-policy --out-dir dist
allowit policy deploy treasury --wasm dist/allowit_custom_policy.wasm \
  --owner-key owner --profile-out treasury.wallet.json

Verify and fund

Read the installed binding and state from the ledger, compare them with the reviewed draft and executable, and verify the host binding with the policy server. Transfer the owner-selected USDC funding amount to the verified wallet in a separate owner-signed transaction. The installed asset identifies the exact USDC contract and issuer.

allowit policy verify treasury --profile treasury.wallet.json \
  --wasm dist/allowit_custom_policy.wasm --rpc-url "$RPC"
allowit wallet fund --profile treasury.wallet.json --owner-key owner \
  --amount "$FUNDING_UNITS"

Execute and reconcile

Give the executing harness the public profile and select the matching agent key. In the agent environment, ALLOWIT_STELLAR_BUNDLE points to that profile, ALLOWIT_URL names the policy server and WALLET is the verified contract address. QUOTE_UNITS is the seller’s accepted price in installed USDC base units. Retain the purchase ID to recover its result. A later redemption and conversion each use a fresh request, their own bounds and the actual output from the preceding operation.

allowit keys use agent
allowit wallet use "$WALLET"
allowit --rpc-url "$RPC" exec --op transfer --to "$SELLER" \
  --amount "$QUOTE_UNITS" --request-id treasury-report-001
allowit --rpc-url "$RPC" status treasury-report-001 --wait 60s

Operations and delegated authority

An owner who gives an agent a signing key still has to decide which payments and conversions it may make, with whom, in what amounts and on what evidence. Allowit divides those decisions among four parties. The owner chooses the wallet, assets, counterparties, limits and executable policy.

An executing agent proposes a specific operation, and the server evaluates it against the approved policy and the relevant evidence. The wallet then verifies the required authorizations and enforces its native rules during execution. Because of this division, a policy can depend on a purchased report without any contract browsing the web.

The initial operation vocabulary comprises transfer, swap, deposit and redeem. These are distinct effect types, with different accounting and receipt requirements. They are not arbitrary contract calls. A wallet's executable advertises the operation types it admits; the owner's operations parameter selects a subset. The Custom policy in the worked example selects transfer, swap and redeem. A vault-deposit mandate selects an executable with deposit support and binds the approved vault and share floor.

Economic operationExact effect and native checksDelegated authority
transferTransfer an exact quantity of the installed asset to the named recipient; apply recipient, amount, expiry and usage constraints. A paid report is a transfer followed by delivery verification.Agent and server authorize the same request; wallet applies the installed policy.
swapSpend an exact input amount through the named router and token path, subject to a deadline and minimum output. On the explicit execute path, the wallet checks its observed input debit and output credit.Agent and server authorize router, path, quantities and deadline; native policy constrains assets, venue and financial bounds.
depositSupply an exact amount of the wallet asset to an approved vault and receive at least the specified share quantity into the wallet. The receipt records underlying debit and share credit.Agent and server authorize vault, underlying amount and minimum shares; the selected wallet executable enforces deposit effects.
redeemBurn a bounded quantity of approved vault shares and receive at least the specified underlying amount into the wallet. The explicit execution path verifies the observed share debit and underlying credit.Agent and server authorize vault, shares and minimum assets; the wallet verifies the effect before retaining the receipt.

The distinction matters economically. A transfer for a consumed service is an expense. A swap or vault conversion moves value between assets or claims; its gross volume and irreversible expense are different quantities. Volume limits bound capital put through operations. Spending limits bound attributable expense, including applicable fees and conversion loss. Amounts use each asset's native integer units. A vault share quantity is not an underlying-token quantity, and a fee denominated in another asset requires authenticated valuation before it can be charged against an asset-denominated limit.

Canonical policy rules

Canonical rules compare authenticated request facts and prior usage with owner-selected constraints. The wallet’s selected enforcement placement determines which checks also run natively.

FunctionConstraint
operationsAllowed native operation class
tokensInstalled asset and swap token membership
destinationsApproved recipient, router or vault
payment_limitGross amount per operation
lifetime_spending_limitCumulative irreversible expense
daily_spending_limitIrreversible expense per UTC day
daily_volume_limitGross volume plus attributable gas per UTC day
call_limitSuccessful operation count
expires_atOwner and request expiry

Evidence and assessment functions

Evidence functions run on the server. They retrieve material or assess a scoped question against preceding-call context; the standing analysis allowance bounds metered work.

FunctionPurpose
marketplace_searchRetrieve candidate services with their sources
internet_searchRetrieve public corroborating evidence
fetchRetrieve specified resource under expected-response binding
systemoneAssess one scoped question against preceding call context
priceSupply asset/amount-bound conversion input
clear_systemone_contextStart a new classifier evidence window

Configuration and state access

Configuration and stored policy state have distinct accessors. Updates participate in the native invocation’s atomic commit.

AccessorEffect
ctx.params[key].ok()Read a required typed owner value
get_stateRead admitted policy state
set_stateStage a policy-state update

Authoring and execution

The owner uses the web app, CLI or policy-authoring agent to draft or revise a policy, then reviews its source, settings and wallet permissions before approving deployment.

An executing agent uses Claude, Codex, Antigravity or a custom harness to propose actions, obtain the server’s decision and sign approved requests with its own key.

The external harness obtains SKILL.md from the Allowit server or uses the CLI to access the same operations. The skill describes the endpoint, public wallet profile, command sequence, policy inspection and operation recovery. A server-supplied skill contains no client private key because the server does not hold it. The customer can augment a local copy with credentials or use another client-controlled store; a dedicated secrets store is recommended. The instructions guide the harness, while authorization and native policy checks enforce its permissions.

Client keys and the server boundary

An executing agent signs with a key in client-controlled storage. The customer chooses how that key is stored: a secrets service, an environment var, or even just part of prompt are some possible choices.

We recommend a dedicated secrets store. Allowit’s server receives the public key and its authorization binding; it never receives or stores the client’s private key. The Allowit open source CLI + SDK offers a local fully auditable and client-configurable key-generation path. A possibility is using our CLI and separate public key metadata from a secret key file. The secret file should use (at least) mode 0600 inside a mode-0700 private directory.

The public wallet profile identifies the agent, wallet and policy binding; it contains no seed. The server stores the public key and its authorized binding, not the client's private key. A local signing process can hold the key without placing its raw bytes in the language model's context.

The agent key identifies the requesting execution authority and lets it consent to an exact operation. It is not the owner's unrestricted wallet key. Giving the agent a signing interface allows unattended work under an approved mandate while preserving a separate server decision and owner administration. Before signing, the client checks that the selected local public key matches the wallet profile and that the request refers to the intended network and binding.

Key OwnershipThe owner configures the native wallet. The client and server sign the same canonical request. The wallet verifies both authorities and the installed policy.OwnerInstall · pauseAdminAgentClient keyServer keyPrivate evidenceSignsSignsSame requestPolicy · action · nonceVersion · expiry · effectWalletCheck both signaturesEnforce native limits

The server evaluates requests through scoped interfaces. Those interfaces expose the submitted operation, the permitted decision or explanation, and the operation's status or receipt. They do not provide an executing agent with database access, private feedback records, unrelated owners' context or provider credentials. The server can use private evidence during an assessment without returning the underlying records.

An agent-key compromise alone does not supply the server's authorization. A server-key compromise alone does not supply the agent's authorization. Both parties can still approve an undesirable operation, and both can collude; the native policy continues to enforce the constraints actually installed in the wallet. This makes placement consequential. An on-chain recipient allowlist or output floor remains enforceable under that collusion. A server-only judgment about report quality depends on the server's assessment. The paper's worked policy assigns deterministic financial constraints to the wallet and contextual assessment to the server for that reason.

Owner administration follows a separate path. The owner can pause delegated execution, change the approved configuration or use the defined recovery authority without asking the executing agent to approve its own removal. Configuration changes advance their version and preserve accounting and replay protection. Delegated signatures do not confer these owner powers.

Rust

Native enforcement

The financial constraints that must hold if the agent or server makes a overly permissive mistake can be compiled into a Common or Custom policy contract and checked each time the wallet is invoked.

The next policy in this example evaluates authenticated operation facts against installed parameters and recorded usage, without making network requests. It first applies shared checks: the permitted operation, the asset, the expiry, expense and daily volume (supported by both Common and Custom contracts). It then branches by operation type (supported in Custom contracts only).

Transfer

The transfer branch admits a payment only when its recipient belongs to evidence_sellers and its gross amount passes payment_limit under report_limit. A transfer to an exchange or vault therefore fails unless that address is also an approved evidence seller. The shared checks still apply: operation, asset, expiry, lifetime and daily expense, and daily volume. Passing these financial checks permits the bound payment; the host separately assesses the report’s relevance, binds the purchased service and terms, and records whether the report actually arrives.

Swap

The swap branch checks swap_venues and swap_limit, then reads typed reserve, floor and output-asset parameters. The request must spend the installed asset and receive the configured token. Reserve must be nonnegative, floor positive, remaining daily capacity at least reserve, and signed min_out at least floor. The host also checks that this minimum satisfies the owner’s slippage tolerance against the accepted reference quote. It binds that minimum into the authorized request; explicit native execution verifies the resulting output. A swap can pass its payment cap yet fail the capacity reserve.

Redeem

The redeem branch checks the vault against the owner’s approved set. A zero share_limit leaves shares uncapped; a positive value bounds request.amount_in, and a negative value denies. The additional policy output floor must be nonnegative, and request.min_out must meet it. Native redemption still requires positive shares and positive minimum asset output. Shares and underlying assets use their own units. Explicit execute verifies the underlying credit rather than trusting the vault’s reported payout. Any later conversion uses the amount actually received and requires its own authorization.

Result and execution

An operation outside the selected branches is rejected; if it reaches the final match arm, the policy panics. Every rule error in this source propagates, and a failed assertion or required typed read aborts evaluation. Native failure rolls back the invocation’s effects. Returning Ok(()) means only that this request passed the policy; it neither submits a transaction nor purchases a service. Host orchestration prepares the operation through its vendor package, collects signatures, persists signed bytes, submits them and reconciles the outcome. Report delivery requires separate evidence.

use allowit::prelude::*;
const EVIDENCE_SELLERS: &str = "evidence_sellers";
const REPORT_LIMIT: &str = "report_limit";
const SWAP_VENUES: &str = "swap_venues";
const SWAP_TOKEN: &str = "swap_token";
const SWAP_LIMIT: &str = "swap_limit";
const RESERVED_VOLUME: &str = "reserved_volume";
const SWAP_OUTPUT_FLOOR: &str = "swap_output_floor";
const VAULTS: &str = "vaults";
const SHARE_LIMIT: &str = "share_limit";
const REDEEM_OUTPUT_FLOOR: &str = "redeem_output_floor";
/// Buy evidence only from approved sellers. Rebalance through approved exchanges,
/// retaining capacity for later work. Redeem only approved vault positions.
/// Bound expenses, volume, assets, expiry and each operation's native effects.
pub fn execute(ctx: &AllowitContext) -> allowit::Result {
    let operation = allowit::operations(ctx, &ctx.params[allowit::OPERATIONS].ok())?;
    allowit::tokens(ctx, &ctx.params[allowit::TOKENS].ok())?;
    allowit::expires_at(ctx, &ctx.params[allowit::EXPIRES_AT].ok())?;
    allowit::lifetime_spending_limit(ctx, &ctx.params[allowit::LIFETIME_SPENDING_LIMIT].ok())?;
    allowit::daily_spending_limit(ctx, &ctx.params[allowit::DAILY_SPENDING_LIMIT].ok())?;
    let remaining = allowit::daily_volume_limit(ctx, &ctx.params[allowit::DAILY_VOLUME_LIMIT].ok())?;
    match operation {
        "transfer" => {
            allowit::destinations(ctx, &ctx.params[EVIDENCE_SELLERS].ok())?;
            allowit::payment_limit(ctx, &ctx.params[REPORT_LIMIT].ok())?;
        }
        "swap" => {
            allowit::destinations(ctx, &ctx.params[SWAP_VENUES].ok())?;
            allowit::payment_limit(ctx, &ctx.params[SWAP_LIMIT].ok())?;
            let reserve: i128 = ctx.params[RESERVED_VOLUME].ok();
            let floor: i128 = ctx.params[SWAP_OUTPUT_FLOOR].ok();
            let output: Address = ctx.params[SWAP_TOKEN].ok();
            assert!(ctx.request.token_in == ctx.request.asset);
            assert!(ctx.request.token_out == Some(output));
            assert!(reserve >= 0 && floor > 0);
            assert!(remaining >= reserve);
            assert!(ctx.request.min_out >= floor);
        }
        "redeem" => {
            allowit::destinations(ctx, &ctx.params[VAULTS].ok())?;
            let shares: i128 = ctx.params[SHARE_LIMIT].ok();
            let floor: i128 = ctx.params[REDEEM_OUTPUT_FLOOR].ok();
            assert!(shares == 0 || (shares > 0 && ctx.request.amount_in <= shares));
            assert!(floor >= 0 && ctx.request.min_out >= floor);
        }
        _ => panic!("unsupported operation"),
    }
    Ok(())
}

Typed input
Result
Accumulated evaluation
RuleInputTyped result
operationsrequest.operation; owner operationsResult<&'static str>
Ok("swap")
tokensinstalled asset; output asset; allowed assetsResult<Address>
Ok(installed_asset)
expires_atowner expiry; request expiry; authenticated nowResult<u64>
Ok(owner_expiry − now)
lifetime_spending_limitlifetime expense; request.spent_units; owner lifetime limitResult<i128>
Ok(lifetime_limit − lifetime_spent − spent_units)
daily_spending_limitUTC-day expense; request.spent_units; owner daily expense limitResult<i128>
Ok(daily_limit − day_spent − spent_units)
daily_volume_limitUTC-day gross volume; request.amount; attributable gas; owner volume limitResult<i128>
Ok(volume_limit − day_total − amount − gas_units)
match operationoperation = "swap"branch selection
Enter "swap"
destinationsrequest.recipient; owner swap_venuesResult<Address>
Ok(approved_venue)
payment_limitrequest.amount; owner swap_limitResult<i128>
Ok(swap_limit − amount)
ctx.params[key].ok()reserved_volumei128
reserve
ctx.params[key].ok()swap_output_floori128
floor
ctx.params[key].ok()swap_tokenAddress
approved_output_asset
assert!token_in == asset()
Pass
assert!token_out == Some(output)()
Pass
assert!reserve >= 0 && floor > 0()
Pass
assert!remaining >= reserve()
Pass
assert!min_out >= floor()
Pass
Ok(())all evaluated checks passedallowit::Result
Ok(())

Beneath the business rules, the custody kernel enforces its own invariants: policy and module identity, network, installed asset, signer authority, pause, expiry, version, nonce and replay. These apply whether or not a policy lists any particular rule.

Submission and reconciliation

If Allowit broadcasts a payment that times out, the transaction may already be queued or settled. Rebuilding and re-signing it could let a second, different transaction settle alongside the first. Allowit therefore persists a journal entry containing the operation ID, the canonical authorized request, and the original network transaction hash derived from that transaction. Restarting resumes this same operation. Similarly, our smart contracts have replay protections.

Stellar RPC’s sendTransaction checks the transaction and queues it. A submission response describes that attempt. After any response or timeout, Allowit queries the original hash with getTransaction. While the outcome is unknown, Allowit holds the spending reservation. It can resend the identical bytes only while both the authorization and the signed transaction remain valid. Stellar RPC: sendTransaction

Submission ReconciliationThe original transaction hash identifies the ledger result. Unknown, successful and terminal unsuccessful outcomes have distinct reservation rules.Save requestSigned bytes + hashSubmitSame signed bytesCheck hashLedger statusUnknownHold; retry if eligibleSuccessSettle effects and feesClosed failureRelease unused funds after fees

On SUCCESS, Allowit records the actual transfers and fees and releases the unused reservation. On a terminal FAILED result, it releases the unused amount after fees. If the result is NOT_FOUND, Allowit keeps the reservation until it can establish both that the original transaction never settled and that it can no longer settle. Stellar RPC: getTransaction

Service discovery

An agent looking for a report on a specific vault finds offers spread across catalogs that describe services and payment in different ways, and a seller's own description says little about what it will deliver. The marketplace gives the engine one place to search these offers. Its records and retrieval storage stay on the server, shared SDK behavior makes discovery available to the command-line tool and other callers, and a vendor adapter handles each service's protocol and payment details.

Indexing normalizes each offer into a provider, a service, a source and a supported operation, together with the terms needed to prepare a purchase. Semantic retrieval matches a task against candidate descriptions. Structured requirements then narrow the candidates by capability and by compatible payment path. Each result keeps its origin, so a seller's description can be told apart from a fact the system observed.

In the treasury mandate, the marketplace query names the vault and the evidence the owner requires. Candidates from sellers outside evidence_sellers may show up in the results, but they cannot be paid, because the native transfer branch checks the destination. The terms that govern a purchase come from a fresh quote or payment challenge, not from the index. Indexing an offer neither fixes the seller's price nor validates the seller's claims.

Marketplace LineageOffers retain their source and provider identity through retrieval and ranking. A current quote enters explicit policy evaluation. Allow binds authorization to that request; deny stops, and ask goes to owner review.Offers with provenancesource · provider identity · capabilityRetrieve and ranktask relevance · attributable outcomesCurrent quoterecipient · asset · amount · operationPolicydecisionallowBound authorizationsame request and exact termsdeny / askDeny: stopAsk: owner review

Reputation records what happened after earlier selections. Each contribution binds an authenticated owner, the request, the subject and the signal type. Suitability, verified delivery and output quality are separate signals, because a seller can deliver reliably and still be a poor fit for a particular vault question. Repeating a vote does not add independent observations. Editing a contribution replaces the earlier one without resetting its age.

Aggregated evidence keeps three populations apart: this policy, the owner's other policies, and other owners. When there is no support at all, the result is reported as unknown. Shared scores are heuristic signals, not probabilities that a purchase will succeed. The ranking model described under model learning combines these records with relevance and current terms, and keeps sparse evidence and conflicting opinions visible instead of averaging them away.

Execution costs

Each operation draws on independently priced services and network resources. The engine retains the applicable tariff or accepted quote with the decision, so the owner can attribute incurred costs to the work that caused them.

Server compute and storage

compute time × rate
+ retained bytes × rate

The host operator prices execution, records and storage retention. The owner’s billing arrangement determines which costs are attributed to a mandate.

Marketplace indexing and retrieval

indexed data + query work

The marketplace operator meters indexing, retrieval and retention, or allocates them within the host service. Discovery does not purchase the selected service.

Web search and fetching

queries / requests × provider rate

The search or retrieval provider sets the tariff. The standing analysis allowance admits paid evidence calls before they occur.

Model inference

input units × input rate
+ output units × output rate

The selected model provider sets its usage tariff. Assessment costs remain attributable when a later operation is denied.

Purchased services and venues

accepted quote + venue charges

The seller sets service terms; the exchange or vault defines its charges. Each accepted payment binds its recipient, asset and amount. x402 payment terms.

Network execution and storage

inclusion + resources
+ storage rent / restoration

The network sets resource pricing. Transaction simulation estimates resources and restoration requirements for the exact proposed invocation. Stellar fee model.

Stellar charges fees in lumens (XLM). One lumen equals 10⁷ stroops. A classic operation costs at least 0.00001 XLM for inclusion, with higher fees during congestion. Contract transactions also pay for computation, ledger access and storage rent. Before signing, the wallet simulates the invocation to estimate its resource fee. Account reserves remain part of the account balance. Stellar fee schedule · Transaction simulation

Allowit could sell subscriptions to its hosted policy engine and meter searches, model calls and other analysis against the owner’s research budget. That work incurs costs even when the engine denies the proposed action. For a marketplace purchase, Allowit could disclose its service fee alongside the seller’s price in the quote the owner authorizes. Institutions could also pay for private deployments, support and model adaptation using records they authorize for training.

Model learning

Allowit conditions each assessment on a scoped evidence record. Owner feedback is stored with its author, policy revision and exact judgment question; its interpretation remains conditional on that owner's preferences and the evidence available at review.

At inference, the model receives the question, preceding policy calls and their results within the active evidence window, and authenticated corrections to the same question. Later calls and the policy-authoring conversation are excluded. A context reset begins a new call window while retaining audit records and applicable corrections. This use of explicit memory follows the distinction between parametric and non-parametric knowledge in retrieval-augmented generation (Lewis et al.). Allowit applies contextual corrections with fixed model weights. Parameter updates use separately curated offline training data, followed by evaluation and explicit model activation.

Learning EvidenceScoped assessments and optional owner answers enter a provenance and data-use review. Authorized records support training, calibration and held-out evaluation before release evaluation and explicit activation.Earlier calls and resultsfor this classifier / questionSystem One scoreOwner thresholds: allow · deny · askaskOwner answerfor this questionRecord review and permissionCheck provenance, outcomes and correctionsAdmit only records authorized for learningTrainingFit behaviorCalibrationFit score mapHeld-out testsEvaluateRelease evaluationOwner-approved decision thresholdsExplicit version activation

Policy generation

Input
Owner intent; admitted policy vocabulary and interfaces; typed parameter schemas
Target
Draft made of an admitted source and typed parameters
Errors
Unadmitted or wrong source; malformed or out-of-range parameter; misread intent
Consequences
Validation rejects malformed drafts. A well-formed error accepted at owner review can grant too much or too little authority
Evaluation
Held-out owners and intents; source admission and compilation checks; behavioral cases against reviewed owner intent

System One assessment

Input
Exact scoped question; preceding calls and their results; authenticated same-question corrections
Target
Basis-point score that the policy compares with owner thresholds to allow, deny or escalate
Errors
False allow; false deny; needless escalation; obeying injected text; trusting stale evidence
Consequences
A false allow can permit an unwanted action within policy limits. False denials and escalations cost coverage and owner time
Evaluation
Held-out periods and providers; false-allow cost and coverage at deny_below and allow_above; separate calibration split; injection and stale-evidence tests

Ranking

Input
Task; candidate reports or listings; provenance and exposure history
Target
Ordering by task relevance and source quality
Errors
Irrelevant item ranked high; syndicated duplicates counted as separate confirmations; exposure bias
Consequences
The owner sees weaker evidence first. The policy and its thresholds stay unchanged
Evaluation
Held-out providers and near-duplicate groups; exposure-aware ranking metrics; delivery and settlement scored separately

The design trains three specialists with separate targets. Policy generation maps an owner's intent to a draft made of an admitted source and typed parameters. Validation and owner review can each reject the draft. System One maps an exact scoped question and its evidence to an assessment.

TypeSafe’s Jev describes this model class as typed decisions inside software. The policy compares that assessment with the owner's thresholds to allow, deny or escalate. Marketplace and news reranking maps a task, its candidates and their provenance to an ordering. Outcome fields stay distinct because each measures something different. Delivery, relevance, source quality, settlement and economic outcome are therefore recorded separately, and each target learns only from the signals that measure it.

Training records and adaptation

Calibration and release

Each training record carries its provenance and the owner's permission for training use. Private feedback trains only within the scope its owner authorized. Records bind the question, policy revision, time and evidence snapshots or content identifiers, so each label retains the evidence available when it was made. Reviewers disagree and some labels are noisy, so the dataset keeps individual judgments and their disagreement rather than one merged answer. Syndicated stories and repeated provider claims are deduplicated, so one story does not count as several confirmations. Interaction feedback covers only the candidates that were shown. The system therefore logs exposure and selection, and keeps that feedback apart from separately curated comparisons over unexposed candidates. Evaluation can then measure exposure bias and correct for it where the correction's assumptions hold. Teacher models can propose labels, but review decides which proposals enter the training data. Rejected requests and hypothetical cases can carry reviewed expected decisions under a stated rubric. They never carry fabricated delivery, settlement or financial outcomes.

System One returns a score in basis points. The raw score has meaning only within its exact question and is not a calibrated probability. Guo et al. found that modern neural classifiers can be miscalibrated, and they evaluated temperature scaling on image and document classifiers. That result does not make a language-model score a probability. If the system uses a calibration map, the map is fitted on a split kept apart from training and test data, and it is versioned with the model. The owner-approved thresholds deny_below and allow_above bound an abstention band. A score satisfying deny_below ≤ score < allow_above sends the question to the owner. Geifman and El-Yaniv show that, under stated assumptions, a classifier that can reject inputs trades coverage for lower risk on the inputs it accepts. The design uses this trade-off without assuming that their guarantees transfer to language-model judgments about finance. Held-out validation reports false-allow cost against escalation coverage under a reviewed decision rubric. Disputed labels stay distinguishable, and the report shows sample support and uncertainty by question and provider. The owner uses that report to choose thresholds, and changed distributions require reassessment.

Training methods are options chosen per target, not stages of a fixed pipeline. Retrieval changes what a model sees without training. Supervised fine-tuning learns from reviewed demonstrations, such as approved policy drafts. Hu et al. describe LoRA, which freezes pretrained weights and trains low-rank update matrices. Each specialist can therefore use a separately versioned adapter on a shared base; rollback preserves compatibility with that base. Hinton et al. distill a large model or an ensemble into a smaller model that is practical to deploy. A distilled student is evaluated on its own results and is never assumed to match its teacher. Ouyang et al. fine-tuned on demonstrations, then used ranked output comparisons for reinforcement learning from human feedback. Rafailov et al. optimize paired preferences against a reference model with a classification loss, without a separately fitted reward model or an online reinforcement-learning loop. Both are precedents, not requirements. Preference methods suit comparative targets. DPO can train language-model outputs that express a ranking, but it is not a general objective for numerical rankers. A pair is valid only when both responses answer the same prompt under the same allowed context. The preferred response records a reviewer's choice, not the truth.

Evaluation holds out owners, providers and time periods, and it groups near-duplicate items before splitting. These splits reduce, but do not remove, the chance that a model earns credit for memorizing a client, a publisher or a story. Attack tests place instruction-like text inside fetched reports and check that the model treats it as evidence about the question, not as a directive. Stale-evidence tests check that the model does not read an old price or a superseded report as current. Regression suites check each release against required behavior. Learning has costs: data curation, training runs, inference, retrieval, and human review of labels and escalations. Comparisons use total cost per reviewed task, including retrieval and escalations, rather than token prices alone; no fixed saving follows. Each release versions the base model, adapters, retriever, prompt templates and calibration map, and it names the threshold versions it was validated against. Activation is explicit. Rollback goes only to a release that is compatible with the active policy's thresholds. Every assessment records the release that produced it. A reviewer can therefore trace a score to that release, the thresholds it was compared with, and the exact policy and authority under which it ran.

Organizational capacity

A small treasury team may understand a position change yet lack the staff to coordinate its research, purchases, reviews and execution. Allowit lets agents carry that sequence forward under an owner-defined policy.

Manidis and Roberts frame the broader economic question around the institutions and controlled positions through which model capabilities become useful. The engine supplies a mechanism for delegating consequential work while keeping authority and execution reviewable.

A larger organization may want a capital movement to pass an operating policy, a departmental budget authority and a risk reviewer, and for exceptional requests an accountable person, before it executes. Such a chain can replace the single server approval.

An owner can assign an executing agent the owner-signing role for a subordinate wallet. That agent can appoint another executing agent and fund its work through a separately authorized parent transfer. Each wallet checks its own agent-and-server authorization and installed policy. Parent funding authorization bounds the transfer; the child’s installed policy governs subsequent execution. When A owns the child, A controls its configuration. Alternatively, making the parent policy wallet the child’s owner routes child administration through the parent’s policy checks.

The retained record connects evidence, classifier judgments, owner answers, signed terms and observed outcomes. New staff or agents can inherit this context; authorized records also support discovery and reviewed training. Explicit research, expense and volume allowances let the owner allocate scarce resources and revise limits without erasing prior commitments.

The same structure supports teams buying data, monitoring, storage or computing services. Agents find providers and compare terms; exceptions return to the responsible owner. Authorization applies to the supported operation. If later use of a purchased resource also needs constraints, those calls require their own governed execution path.

Delegation HierarchyThe owner assigns child administration to agent A. A signs parent operations and separately owns the child wallet. Parent authorization bounds funding; the child policy governs subsequent operations authorized by B and the child server.OwnerInstalls parent policyExecuting agent AParent execution keyParent policy serverParent decision+ signatureParent policy walletA + server; parent constraintsDelegates child administration to AA as child owner signerApproves child policy and authoritiesSeparately authorized fundingExecuting agent BChild execution keyChild policy serverChild decision+ signatureChild policy walletB + server; child constraints

We believe that we are at the Dawn of a new era of agentic value creation. As new flywheels accelerate with less friction than we thought possible even a few years ago, small hybrid teams will perform work of previously unimaginable complexity in record time. To enable this momentum, we’ll need new self-balancing systems that keep our algorithmic cars from tipping over as they turn into hyperloops. Allowit sees itself as one of the foundational research and development collectives building the axles that will carry us along the rails of the future.

References