paybondpaybond
Sign in

Middleware performance and latency

Honest overhead model for Paybond agent middleware — serial Gateway/Harbor hops per guarded tool call, what dominates latency, dev trace limits, and production observability.

Paybond agent middleware adds policy enforcement and evidence around side-effecting tool calls. For architects sizing agent workloads or comparing guarded vs unguarded tool latency, the important fact is simple: network round trips dominate — not local policy parsing or evidence JSON construction.

This guide describes the typical online path per guarded tool call, what adds latency, what the dev trace dashboard does not measure, and how to observe middleware overhead honestly in production. For integration mechanics, see Agent middleware. For the trace event model, see Middleware trace.

No published Kit p50/p99

Paybond does not publish middleware latency benchmarks. Hosted latency depends on region, tenant load, Harbor health, and your tool handler time. Use Gateway upstream SLIs and your own APM around guarded tool boundaries — not fabricated percentile tables.

What middleware adds

Middleware work splits into two buckets:

BucketExamplesTypical cost
Local (small)Policy YAML load, registry resolution, evidence payload build, payee/recognition signingSub-millisecond to low milliseconds on the same host
Network-bound (dominant)POST /verify, POST /v1/spend/decisions/{id}/complete, evidence submit, optional MPP voucher finalizeOne or more HTTP hops per phase — usually low tens to low hundreds of ms per hop on healthy hosted infra

For fast tools (cache lookups, lightweight API calls), Paybond hops often exceed handler time. For slow tools (human approval, large file uploads, multi-second vendor APIs), middleware overhead is usually a smaller fraction of end-to-end latency.

Per guarded tool call — typical online path

The interceptor in kit/ts/src/agent/interceptor.ts (Python parity in paybond_kit.agent) runs a serial cycle for each registered side-effecting tool:

Kit middleware Gateway Harbor | | | |-- POST /verify --------->| auth + tenant scope | | | Postgres idempotency | | | optional spend-policy eval | | |-- POST /verify (mTLS) ------->| capability verify |<-- allow + decision_id --|<------------------------------| | | | | [local tool handler — not Paybond overhead] | | | | |-- POST .../complete ---->| finalize spend decision | | | optional MPP voucher finalize | | |-- internal finalize --------->| (stripe_mpp session) |<-- consumed/released -----|<------------------------------| | | | |-- evidence submit ------>| sandbox guardrails OR | | | recognition + fraud gate + | | |-- POST .../evidence --------->| predicate VM |<-- predicate result ------|<------------------------------|

Phases in order:

  1. AuthorizePOST /verify through Gateway. Harbor validates the capability token and spend amount; Gateway may apply spend-policy locks and idempotency in Postgres before/after the Harbor forward.
  2. Execute — Your tool handler. Paybond does not instrument vendor latency beyond durationMs on the tool_executed trace event.
  3. CompletePOST /v1/spend/decisions/{decision_id}/complete marks the spend decision consumed (or released on handler failure). Stripe MPP session mode may add an internal Harbor voucher finalize hop during completion.
  4. Evidence — Auto-evidence after a successful handler:
    • Sandbox bind — Gateway-composed guardrails evidence route (simulator lifecycle).
    • Production attach — Local payee + agent-recognition signing, then POST /harbor/intents/{id}/evidence with Gateway recognition verification and fraud hardening before Harbor proxy.

Settlement confirm (released / refunded) is a separate Harbor mutation — not included in per-tool middleware latency unless your integration calls it inline after each tool.

Tenant isolation

Every hop uses tenant scope from authenticated credentials (API key, operator session). Kit never sends a client-supplied tenant id. Gateway rejects tenant mismatches before forwarding to Harbor.

Latency factors

FactorEffectMitigation
Serial verify → complete → evidenceThree or more HTTP round trips per guarded tool callBatch work into fewer side-effecting tools; combine read-only steps outside Paybond
Split authorize / executeFrameworks like Vercel AI may call authorize before executeAuthorization cache reuses a fresh verify for 120 seconds when operation, spend, and tool name match — see below
Gateway spend policyPostgres evaluation and row locks on /verifyScope policies narrowly; avoid global per-tenant locks across unrelated operations
mTLS Gateway ↔ HarborFixed TLS + forward cost on every Harbor proxyCo-locate regions; monitor Gateway→Harbor error SLI (production operations §3.2)
Harbor upstream timeoutGateway Harbor clients use a 30s per-request timeoutTreat sustained approach to timeout as infra incident, not retry storm
SDK retry policyDefault 3 attempts on 429 / 5xx with exponential backoff (cap 5s per wait) and Retry-After (cap 30s); Cloudflare edge hints cap at 8sUse idempotency keys; keep upstream healthy to avoid tail latency on blips
Production evidence pathRecognition proof verify + fraud gate + Harbor evidence proxyPre-validate payloads with paybond policy validate-evidence before production attach
verify_capability rate limitDefault 240 requests per tenant per minuteSize agent concurrency; split tenants or stagger bursts
MPP voucher verify limitSeparate limiter when x-paybond-payment-authorization is present (default 120/min, env-tunable)Session-mode metering adds verify-side work — expect extra Gateway time
Offline dev (--offline)Zero Paybond network hopsLocal rehearsal only — not representative of production latency

Qualitative overhead model

Without publishing fabricated percentiles:

  • Expect roughly one RTT per Paybond phase on healthy hosted infrastructure — often ~20–150ms per hop within the same region, plus handler time.
  • Multi-hop serial calls dominate for sub-100ms tools.
  • Transient upstream errors can add several seconds of SDK retry backoff on tail paths.
  • Signal lifecycle latency (intent outcome → reputation) operates on hours scale — not per-tool-call middleware time.

Authorization cache (split approve / execute)

Some agent frameworks separate tool approval from tool execution (for example Vercel AI SDK human-in-the-loop). Paybond caches a successful authorize result for 120 seconds (AUTHORIZATION_CACHE_TTL_SEC in kit/ts/src/agent/authorization-cache.ts).

The cache key is toolCallId:operation. A cached entry is reused in wrapExecute only when operation, requestedSpendCents, and toolName still match. Expired entries are evicted on the next authorize.

When it helps: approve now, execute seconds later without a second /verify.

When it does not apply: single-shot wrapExecute without a prior authorizeToolCall always calls /verify once. Mismatched spend or renamed tools miss the cache.

What dev trace shows — and what it does not

paybond dev trace and traceSink events label middleware phases, not network profiling.

Trace eventWhat it measures
tool_selectedRegistry resolution — timestamp only
spend_authorizedAuthorize phase completed — no RTT field
tool_executedHandler wall time via durationMs only
spend_finalizedComplete phase completed — no RTT field
evidence_submittedEvidence phase completed — no RTT field

The durationMs on tool_executed is your local handler, not Paybond authorize or evidence latency. Use the trace dashboard to debug whether each phase ran and in what order — see Middleware trace — not to size production p99.

Hosted sandbox smoke may print trace_url and console dossier links; those surfaces still omit per-hop network timing until you add your own instrumentation around Kit calls.

Production observability

Kit runs in your infrastructure. Paybond observes middleware from the Gateway and Harbor side:

SignalWhereUse for
Gateway→Harbor error rateLoad balancer / gateway metricsUpstream blips affecting every guarded call
harbor_unreachable / harbor_unavailableGateway JSON errorsIncident correlation with middleware failures
OpenTelemetryGateway, Harbor when OTEL_EXPORTER_OTLP_ENDPOINT is setService-side spans — not Kit-internal
Console intent dossier/console/operations/intents/{id}Post-hoc audit of authorize → evidence → settlement
Signal lifecycleIndexer lag SLIsIntent-outcome reputation — not per-tool latency

Recommended partner pattern:

  1. Wrap guarded tool entry/exit in your APM (OpenTelemetry, Datadog, etc.) with intent_id, operation, and tool_call_id attributes.
  2. Alert on Gateway→Harbor SLIs from Production operations v1 §3.2.
  3. Treat predicate_passed: false as a business outcome — not a retryable transport error (Disputes and evidence).

Reducing perceived latency

Practical patterns that preserve guardrails:

  • Fewer side-effecting tools — consolidate paid vendor calls behind one guarded operation when policy allows.
  • Read-only tools outside the registry — do not register passthrough tools that never spend.
  • Pre-validate evidencepaybond policy validate-evidence catches schema issues before production attach signing.
  • Healthy idempotency keys — reuse stable keys per toolCallId so retries do not multiply Harbor work.
  • Regional co-location — run agents in the same region as your Gateway deployment when possible.
  • Offline rehearsalpaybond dev loop --offline for policy and trace UX without network variance.

Where to go next