Send only what the model needs. Keep a receipt of why.
Runtime defense for AI agents: deterministic, in milliseconds, before every model call.
Measured on the prompt-injection benchmark
-
Attack success rate
−91%
with Next Moca, mean of three runs
-
Task completion
+18.5
points more work completed under attack
-
Model spend
−31%
on the same tasks, before any Next Moca fee
-
Runtime check
11 ms
median round trip
Means across our three runs of AgentDojo, ETH Zurich's prompt-injection benchmark, October 2026: 949 attacked tasks per arm on GPT-4o (twice) and 5,040 paired runs on Gemini 2.5 Flash, each against a same-day baseline with no defense. Round trip from the 5,040-run study.
One API call to secure your agent-model communication
One call sits between your agent and every model call. It takes tool results, documents, memory and messages, and hands the model what the step needs, word for word.
-
01
Select
Keeps the records this step needs. Nothing is rewritten or summarised.
-
02
Scan
Attacks that arrive inside what the agent reads, from an instruction planted in a document to a tool result an attacker wrote, are quarantined before the model sees them.
-
03
Enforce
Your policies run on every call, in front of the guardrails and gateways you already use.
-
04
Record
A receipt for every decision: what was sent, what was set aside, and why.
Recorded call · Support assistant, one doc page poisoned
“I deleted a user with auth.admin.deleteUser but their old access token can still call my API. Why is that happening and how can I stop it?”
Every page the answer needs was kept. The forum post carrying the attack never reached the model.
Recorded call with TypeSafe AI's Jev on TypeSafe's RAG cookbook: 81 pages of Supabase auth docs, one a planted prompt injection. See real recorded calls
Up and running in minutes. Under ten lines of code.
SaaS
Call our API from your stack in under ten lines of code.
from langchain.agents import create_agent
from needlepath_langchain import NeedlepathMiddleware
# NEEDLEPATH_API_KEY is read from the environment. Nothing else in the agent changes.
agent = create_agent(model, tools, middleware=[NeedlepathMiddleware(operating_point="np-2026-10-r6")])
answer = agent.invoke({"messages": [("user", "Which Corvane Freight purchase orders are still open past their delivery date?")]})import os
from needlepath import NeedlepathClient, ContextRecord, TaskSpec
from openai import OpenAI
client = NeedlepathClient(api_key=os.environ["NEEDLEPATH_API_KEY"], operating_point="np-2026-10-r6")
# One record per item the agent holds: purchase orders, the supplier contract, the conversation so far.
records = [ContextRecord(text=po.text, kind="external_data", id=po.id, title=po.title) for po in purchase_orders]
prompt = "Which Corvane Freight purchase orders are still open past their delivery date?"
result = client.select(records=records, task=TaskSpec(prompt=prompt), max_context_tokens=4000)
context = result.rendered_context if result.applied else "\n\n".join(r.text for r in records)
# Your model call, unchanged, with the context ahead of the prompt.
answer = OpenAI().chat.completions.create(
model="your-model", messages=[{"role": "user", "content": f"{context}\n\n{prompt}"}]
)import { NeedlepathClient } from "@nextmoca/needlepath-sdk";
import OpenAI from "openai";
const client = new NeedlepathClient({ apiKey: process.env.NEEDLEPATH_API_KEY!, operatingPoint: "np-2026-10-r6" });
// One record per item the agent holds: purchase orders, the supplier contract, the conversation so far.
const records = purchaseOrders.map((po) => ({ text: po.text, kind: "external_data", id: po.id, title: po.title }));
const prompt = "Which Corvane Freight purchase orders are still open past their delivery date?";
const result = await client.select({ records, task: { prompt }, maxContextTokens: 4000 });
const context = result.applied ? result.response!.renderedContext : records.map((r) => r.text).join("\n\n");
// Your model call, unchanged, with the context ahead of the prompt.
const answer = await new OpenAI().chat.completions.create({
model: "your-model", messages: [{ role: "user", content: `${context}\n\n${prompt}` }],
});# config.yaml: every client behind the proxy gets selection, with no client-side change.
guardrails:
- guardrail_name: "needlepath"
litellm_params:
guardrail: needlepath_litellm.NeedlepathGuardrail
mode: "pre_call"
default_on: true
operating_point: "np-2026-10-r6"
history_max_tokens: 8000
preserve_recent: 2
# export NEEDLEPATH_API_KEY="np_live_..." in the proxy's environment, then: litellm --config config.yaml# One record per item the agent holds. Use rendered_context from the response ahead of the prompt.
curl https://api.nextmoca.com/v1/context/select \
-H "Authorization: Bearer $NEEDLEPATH_API_KEY" -H "Content-Type: application/json" \
-d '{
"records": [
{ "id": "po-2026-0412", "kind": "external_data", "title": "PO 2026-0412, Corvane Freight", "text": "..." },
{ "id": "contract-corvane", "kind": "external_data", "title": "Corvane Freight delivery terms", "text": "..." }
],
"task": { "prompt": "Which Corvane Freight purchase orders are still open past their delivery date?" },
"budget": { "max_context_tokens": 4000, "operating_point": "np-2026-10-r6" },
"render": true
}'Four answers before you decide.
What does Next Moca do?
Before each model call it screens what your agent is about to read, keeps the records the step needs, quarantines attacks that arrive in them, applies your policies, and returns a receipt. Nothing in your agent code changes.
Does it rewrite or summarise my documents?
No. The model reads your own records, word for word. Whole records are kept or set aside; none is rewritten.
What happens when it is not sure?
When Next Moca cannot prove a smaller context is safe, the whole set goes through unchanged, so what you risk on that call is paying full price.
Does it replace my guardrail or gateway?
It runs in front of them. Your guardrail reads less and finishes faster, and your gateway gets a receipt on every call.
Talk to one of our founders
About fit, and how this applies to your business.
Prefer a calendar? Book a time
Thanks. Expect us to get in touch soon.
In the meantime, you can also reach us directly at kiran@nextmoca.com or swanand@nextmoca.com.