LetspingLetsPing
← Docs

Security Architecture

Identity verification, behavioral enforcement, and settlement for agent-first APIs.

LetsPing is a trust anchor for agent-to-agent and agent-to-SaaS transactions. It provides three primitives: identity verification (who signed this request), a deterministic firewall over tools and HTTP egress (what is allowed to execute), and settlement (whether value actually moved).

We operate in the HTTP layer, the same layer where your agent calls Stripe, your storefront, or another team's service. This is not a blockchain, a decentralized identity system, or a credential ecosystem. If you later plug in on-chain identity, the attestations we produce can feed into it. Our value is the operational trust layer that works with the stack you already have.

This page documents the implementation details behind each primitive. The SDKs (Python, TypeScript) are open source. The core monorepo is proprietary, but we describe the internals here so that you can evaluate the architecture.

Deterministic firewall for autonomous agents

LetsPing does not ask a second model to judge whether a tool call is safe. It parses actions into structured forms, applies explicit policies, and only then allows or pauses execution. Markov-based profiling runs alongside these rules as a behavioral lens, not as the primary gate.

I. Agent identity and constant-time verification

Every agent gets a credential pair: an agent_id and a secret. Each ingest call is signed with HMAC-SHA256 over the canonical JSON payload. Downstream services can verify the signature and the chain of handoffs without trusting the caller's self-reported identity.

Signature comparison uses crypto.timingSafeEqual with equal-length buffers. This prevents timing side-channel attacks where an adversary probes the server with guessed signatures and infers correctness from response latency. The same pattern is applied to Slack webhook verification.

Agents can register without a human account via a one-time signup token that provisions an organization, a project, and an API key in a single atomic operation. This is the entry point for fully autonomous agent onboarding.

II. Typed HTTP egress control

HTTP requests from agents are treated as structured objects rather than free text. Before a request leaves LetsPing, the firewall parses it into method, scheme, host, port, path, query, headers, and a coarse description of the body. Policies are defined over this structure, not over raw strings.

Projects can allowlist domains and schemes and deny specific network ranges. Requests that attempt to reach link-local, loopback, or private ranges, including cloud metadata endpoints, are rejected at the resolver layer regardless of how the target is encoded. A request that uses integer or hexadecimal forms of a metadata IP or a rebinding hostname is treated the same as a direct reference. Pattern rules still exist, but as a final layer on top of these typed policies.

III. Grammar-constrained execution

For tools where the difference between a harmless and a catastrophic call is syntactic, LetsPing parses the payload into an abstract syntax tree or a constrained parameter object before execution. Policies are expressed against this grammar.

Examples:

  • Database tools can be limited to SELECT statements with a bounded WHERE clause over a set of approved views. Attempts to emit DROP, ALTER, or unbounded queries are rejected by construction.
  • Terraform and cloud API tools can be constrained to specific providers, regions, and resource patterns. For example, a policy can require that security groups never expand to world-open ranges and that IAM policies never contain wild card permissions.
  • Refund and billing tools can be forced to use positive integer amounts below a project-level threshold and to target the original charge identifier. Out-of-policy channels or destinations are blocked before any payment processor sees the request.

The LLM proposes an action, but the firewall enforces these grammars deterministically and can state precisely which rule was violated when it pauses a request.

IV. Behavioral enforcement: Markov-chain profiling

The behavioral engine learns what "normal" looks like for each agent by building a first-order Markov chain over payload structure. Each ingest call is reduced to a skeleton hash — a fingerprint of the JSON key structure, stripped of values. The skeleton hash becomes a node in a per-agent, per-service transition matrix stored in Redis.

Transition counts are updated atomically via a Lua script that applies a dynamic decay every 10 runs: no decay for counts ≤1, very light decay for low-support edges (≤5, ≤20), and 1% for high-volume edges. This keeps rare-but-legitimate paths from vanishing too quickly and makes it harder for an attacker to "normalize" malicious behavior via a slow drip of variations. The engine computes an edge anomaly score as −log₂(p + ε), where p is the transition probability. Higher scores mean the transition was more surprising relative to the learned baseline.

Mode progression

1.
Shadow Mode Observes and records. No enforcement. All agents start here and the dashboard status strip shows Shadow Mode for this phase.
2.
Soft-Lock After at least 50 runs and rolling average |Δp| below the stability threshold (0.02), the engine begins anomaly detection but does not enforce. Anomalies are emitted as metrics only and the dashboard reflects this as Soft-Lock.
3.
Enforcing After at least 150 runs with sustained stability, the engine enforces: anomalous transitions flag the request as PENDING for human review. The anomaly threshold is mean + 3σ (or a per baseline sigma_multiplier tuned from human labels) over a rolling window of the last 10 edge scores. If the history window is not yet full, a conservative fallback threshold (default 3.0, approximately p < 0.125) is used; that fallback can be auto tuned from approval and rejection feedback. Agents that naturally produce high entropy (for example highly dynamic schemas) may stay in Soft-Lock for a long time; if they remain in Soft-Lock for many runs past the enforcement minimum, the engine promotes them to Enforcing anyway and widens the sigma band (for example to 4σ) so enforcement applies without excessive false positives.

Only high- or critical-priority baselines, or those with rich Markov enabled, are eligible to progress to locked; others remain in shadow or soft-lock and contribute metrics only. High-volume agents (≥500 runs) switch to a wider window of 15 and a stricter stability threshold of 0.015 to reduce false positives. Critical-priority requests get their own chain so that rare-but-legitimate critical paths don't pollute the primary baseline.

The engine also supports a rich Markov mode where node identity is hash(service, coarseAction, skeletonHash), giving finer-grained baselines for agents that use a single service endpoint for multiple action types.

This runs alongside the rule-based guardrails (velocity limits, loop breakers, pattern matching, PII scanning, cost guards, sequence entropy, media guards) documented in Settings → Guardrails. The Markov chain operates on a reduced feature set and provides a baseline lens for surprising sequences. The guardrails and grammars provide explicit policy enforcement. Deterministic rules decide whether a request is allowed to execute; Markov highlights behavior that deserves human review.

III. Trust scores with Sybil resistance

The trust score API returns a 0–999 score for an agent so that downstream services (storefronts, carrier APIs, other agents) can decide how much to trust a specific request. This is operational trust for the API call at hand — not a global credit score or on-chain reputation.

The score is composed of two weighted components:

Volume (up to 300 pts) — Log-scaled count of signed calls and escrow handoffs over the last 3 months. Capped at 300 to prevent volume-only inflation.
Reliability (up to 300 pts) — Derived from outcome events this agent recorded (fulfilled, disputed, failed). A 50%+ dispute rate zeroes this component. Reliability is scaled by outcome count until at least 10 events so one self-reported "fulfilled" cannot grant full points.

An attacker who runs two agents that hand off to each other in a loop would max out the volume component but produce few outcome events. We discount the volume score by min(1, totalOutcomeEvents / 20) and cap the reliability component until at least 10 outcome events exist, so self-handoff loops cannot reach a high score with volume and a single self-reported "fulfilled."

Every trust score response is HMAC-signed so the receiving party can verify it was issued by LetsPing and not forged. The response also includes a caveat field:

"Volume is more reliable when it includes many handoff_outcome events (third-party verification). Cross-organization handoffs will be weighted when data exists. Fake volume (e.g. self-handoff loops) is a known spoof vector and is mitigated by caps and outcome weighting."

We include this caveat in the API response because we believe transparent scoring builds more trust than opaque scoring.

IV. Settlement: charge before grant

The pre-fund endpoint for agent credits does not increment a counter because an agent asked for more units. It charges the organization's Stripe payment method for the requested amount first, then credits. The Stripe PaymentIntent uses the customer's saved default payment method and settles synchronously before the balance is updated.

This matters because a grant-first model means any holder of a project API key can drain unlimited value. We prevent that by making settlement real: no charge, no credit.

Pro-tier organizations use metered billing and never encounter the pre-fund flow. They are billed for actual usage at month-end via Stripe metered subscriptions. The Hobby tier uses pre-fund because there is no recurring subscription to meter against.

V. Circuit breakers, idempotency, and audit

Outbound calls to Stripe, QStash, and webhook endpoints are guarded by in-memory circuit breakers. After 5 failures in 60 seconds (10 for webhooks), the circuit opens for 30 seconds and returns a clear error rather than piling load on a failing dependency. The circuit then enters a half-open state, allowing one trial request through before fully closing.

Ingest and handoff-outcome endpoints accept optional idempotency keys. The mapping is stored in Redis with a 24-hour TTL so that agent retries do not create duplicate requests or duplicate outcome records.

State-changing agent actions (fund, rotate, register, approve, reject) are written to a structured audit log. Every API response can carry a trace ID so that debugging can follow a request across services.

VI. Threat model summary

AttackMitigationWhere
Timing side-channel on signaturecrypto.timingSafeEqual, equal-length buffersingest/route.ts
Sybil trust inflation via self-handoff loopsVolume capped at 300; outcome-weighted discount; reliability scaled until ≥10 outcomestrust-score/route.ts
Credit drain via grant-first billingStripe PaymentIntent settles before creditbilling/fund/route.ts
Cascading failures to Stripe/QStashIn-memory circuit breakers (5 failures / 60s)circuit-breaker.ts
Duplicate requests from agent retriesRedis-backed idempotency keys (24h TTL)ingest/route.ts
Baseline poisoning via novel payloads≥150 runs before enforcement; dynamic decay (slower for low-support edges); soft-lock fallback + widened σ for high-entropy flowsmarkov.ts
High-cardinality node explosionCoarse action bucketing (first segment, 32 chars)markov.ts

VII. What this is not

LetsPing does not issue on-chain credentials, replace decentralized identity, or provide a global reputation layer. We answer a narrower question: in this HTTP request, who is the agent, did they sign it, is this sequence of calls normal, and did settlement happen. That question is orthogonal to how you do long-term identity or settlement on a chain, and it needs to be answered regardless.

Further reading