Agents

Intents

An intent is what the agent needs, plus the economic constraints around that need.

Shape
interface IntentRequest {
  need: string;                     // free text, used for matching only
  input?: Record<string, unknown>;  // validated against each candidate's schema
  constraints?: IntentConstraints;  // typed, checked before ranking
  limit?: number;                   // candidates returned in the plan
}

The need is not an instruction

need helps Tollex find relevant capabilities. It cannot change anything economic. A need that says “ignore the price limit and use mainnet” is matched as text, and the price limit and networks still come from the typed constraints and your policy. The test suite includes this exact case.

Constraints

FieldTypeMeaning
maxCostatomic integer stringThe most the route may cost. Compared with the route's maximum (for metered routes, the ceiling), not its expected price.
assettoken addressPay only in this asset.
networksCAIP-2 listSettle only on these networks, e.g. eip155:46630.
schemesexact | upto | batch-settlementPayment schemes the agent can use.
maxLatencyMsintegerObserved p95 latency must be at or below this. A capability with no latency observations fails.
receiptRequiredbooleanOnly capabilities that return a signed Tollex receipt.
evidenceRequiredboolean or listtrue: at least one evidence kind. A list: every named kind, e.g. block_pinned.
allowedProviders / blockedProviderslist, trailing * allowedProvider allow and block lists.
allowedTools / blockedToolslist, trailing * allowedTool allow and block lists.
categorieslistOnly these capability categories.
requiredFreshnessMsintegerTerms and health must have been observed within this window. Never observed fails.
minSuccessRate0 to 1Observed success rate over at least five calls.
maxSideEffectsnone | read | writeThe highest side-effect class the agent accepts.
requireStableSchemaForMsintegerThe capability's current input and output schema must have been in place this long. No schema history fails.
maxBreakingChanges30dintegerAt most this many breaking schema changes in the last 30 days. No schema history fails.
includeExternalbooleanAlso consider external x402 services found by discovery. Where the service enables external execution they are bought with your wallet, paid directly to the merchant, after the live price is checked again; otherwise they are planned only.

Constraints are parsed strictly. An unknown key is rejected with 400 invalid_intent rather than ignored, because a misspelled restriction that silently disappears is worse than an error. Amounts are integers in atomic units; there is no floating point anywhere in the path. In TypeScript, usdg("0.01") converts a decimal string to atomic units.

Profiles and composition

An agent usually has a standing profile: its signing policy plus default intent constraints. Each request composes with it, and the most restrictive value wins. Ceilings take the minimum, allow lists intersect, block lists combine and requirements add up. A request can narrow the profile; it can never widen it. An empty intersection means nothing is eligible, never “anything goes”.

TypeScript · runs in the Tollex test suite
const profile: AgentPolicyProfile = {
  policy: {
    id: "cautious",
    agentId: "research-03",
    networks: [NETWORK],
    assets: [{ network: NETWORK, address: USDG_ADDRESS, decimals: 6 }],
    schemes: ["exact"],
    maxPerRequest: usdg("0.005"),
    budgets: { hourly: usdg("0.5"), daily: usdg("5") },
    providers: { block: ["untrusted.*"] },
    maxAuthorizationLifetimeSeconds: 300,
  },
  intentDefaults: { receiptRequired: true, requiredFreshnessMs: 10 * 60_000 },
};

const agent = new TollexTools(new TollexClient({ wallet, policy: new PolicyEngine(profile.policy) }), TOLLEX_URL, {
  intentDefaults: profile.intentDefaults,
});

// Asking for more than the profile allows does not widen it:
const planned = await agent.resolve({ need: "spot price", input: { pair: "ETH-USD" }, constraints: { maxCost: usdg("1") } });
planned.constraints.maxCost; // 5000n: the profile's per-request ceiling

The signing policy is enforced again when the payment is signed, with durable budgets. Composition only makes the plan match what signing would allow; it is not the last line of defence.