Runtime Scans
Execute hosted red-team probes through the actual agent code running in development, CI, staging, or production.
Runtime scans exercise your application's agent directly. ZeroLeaks invokes a local RuntimeScanTarget through an authenticated relay, preserving the agent behavior that a system prompt or limited HTTP interface may not capture.
Target contract
interface RuntimeScanTarget {
describe(): RuntimeTargetDefinition | Promise<RuntimeTargetDefinition>;
invoke(input: RuntimeTargetInvocation):
| string
| RuntimeTargetResponse
| Promise<string | RuntimeTargetResponse>;
reset?(sessionId: string): void | Promise<void>;
}invoke() receives:
message: the current attack prompt;messages: complete history for this isolated session;sessionId: stable across a multi-turn sequence;signal: cancellation and timeout signal;- scan and event identifiers for logging or correlation.
Structured responses
Return text alone or a structured response:
return {
text: result.text,
messages: result.messages,
finishReason: result.finishReason,
usage: result.usage,
toolCalls: result.toolCalls.map((call) => ({
id: call.id,
name: call.name,
arguments: call.arguments,
result: call.result,
error: call.error,
providerExecuted: call.providerExecuted,
})),
};When messages is omitted, the SDK appends the returned text as an assistant message. Return the complete post-invocation history when your framework emits tool and assistant messages that must be retained for later turns.
Relay lifecycle
- The SDK polls only while
runtimeScans.run()is active. - Invoke and reset events are claimed so two runners cannot normally execute the same event.
- Independent sessions execute concurrently by default, while events within each session stay ordered.
- Abandoned claims become available again after a short lease.
- A target invocation has a bounded server wait; runner errors are attached to the scan.
- The hosted scan uses durable stages: reconnaissance and target profiling, then the secrets-in-context, injection, and agent-probe tracks in parallel, then report finalization.
- The three reconnaissance questions arrive as ordinary invoke events before any attack.
- Aborting, timing out, or detecting a stalled hosted worker cancels the run instead of leaving it indefinitely marked as running.
Use eventConcurrency to tune local execution when your target has stricter rate limits:
await zeroleaks.runtimeScans.run(target, {
eventConcurrency: 4,
workerStallTimeoutMs: 6 * 60_000,
scan: { scanMode: "full" },
});full is the default runtime scan mode. It combines secrets in context, adaptive injection, target-specific boundary probes, and the complete production probe catalog. Full mode always covers every attack surface, ignores attackSurfaces, uses the production knowledge profile unless you ask for research, and raises maxAdaptiveCandidates to at least 10.
quick omits the production catalog, caps adaptive boundary probes at 4, and honors attackSurfaces, knowledgeProfile, and maxAdaptiveCandidates. Use it for development smoke tests.
What is stored
The target definition and options you send are stored so the hosted workflow can replay them against your agent. API reads redact credential-shaped values from target and options. When the scan ends, the stored copy is rewritten with those values redacted. The report's target receives the same redaction. Keep real credentials out of instructions and metadata even with these protections.
Existing target objects
Use defineRuntimeTarget() when your application already implements the interface:
const target = defineRuntimeTarget(myTarget);
await zeroleaks.runtimeScans.run(target);Use createRuntimeTarget() when wrapping functions and metadata separately.