Overview
TheOffensiveSecurityAgent is the core agent harness that powers all specialized agents in Pensar Apex. It handles tool creation, stream management, and result resolution, allowing specialized agents to focus solely on their domain-specific logic.
The agent owns tool creation — all available tools are built from the session context, and specific agents select which ones to activate via the activeTools array.
The stream starts immediately on construction — no need to call a separate .run() method.
Key Features
- Automatic Tool Management: Creates and manages all available tools from session context
- Streaming by Default: Stream starts immediately on construction
- Flexible Consumption: Multiple ways to consume the stream (callbacks, async iteration, raw stream)
- Type-Safe Results: Generic type parameter
TResultfor typed return values - Approval Gate Integration: Optional approval gate for human-in-the-loop operations
- Credential Management: Automatic credential resolution without exposing secrets to the model
Constructor
Configuration object for the agent
OffensiveSecurityAgentInput
System prompt defining agent persona and behavior
Initial user prompt that kicks off the agent
AI model identifier (e.g.,
"claude-sonnet-4-20250514")Session providing paths for findings, POCs, logs, etc.
Which tools the agent is allowed to use. Accepts both built-in tool names and custom tool names from
extraTools.The target URL / host — passed to browser tools for context
Additional tools to merge into the toolset. Use this to inject agent-specific tools without modifying the shared tool registry.
Existing conversation history (for resumption / multi-turn)
Condition(s) under which the agent should stop
Strategy for selecting which tool to call
Callback fired after each agent step completes
Callback fired when the entire stream finishes
AbortSignal to cancel the agent mid-run
Per-provider API key overrides
When set, tools like execute_command / http_request / create_poc route execution through this sandbox instead of running locally
Shared findings registry for cross-agent dedup. When present,
document_vulnerability checks for duplicates before writing.In-memory credential store. When present, tools resolve credential IDs to secrets at execution time — the agent never sees raw passwords or tokens.
Called after the stream is fully consumed to produce a typed result. If omitted,
consume() returns void.Zod schema for structured output via the
response tool. When provided, the base class automatically creates and injects a response tool, merges hasToolCall("response") into stop conditions, and defaults resolveResult to return the captured structured data.When provided, each tool call is gated through the approval gate. The gate will pause execution until the operator approves or denies the call.
Identifier for this agent when running as a subagent
Callbacks for forwarding subagent stream events to the parent consumer
Callbacks for persisting agent discoveries to external storage (e.g., database)
Methods
consume()
Consume the stream with typed callbacks, then resolve the final result.Optional callbacks for stream events
The value produced by
resolveResult, or void if none was providedConsumeCallbacks
Called when text is streamed from the model
Called when a tool is invoked
Called when a tool returns a result
Called when an error occurs
Callbacks for forwarding subagent events
Properties
streamResult
The underlying Vercel AI SDK stream result — escape hatch for advanced use.fullStream
The raw async-iterable stream of chunks. Equivalent tostreamResult.fullStream.
response
Promise that resolves to the final response metadata once the stream has been fully consumed.Usage Examples
Basic Usage with Callbacks
Async Iteration
With Structured Output
With Approval Gate
With Credential Manager
Consumption Patterns
The agent stream can be consumed in three ways:- Typed Callbacks
- Async Iteration
- Raw Stream
The underlying stream can only be consumed once. Choose one consumption pattern per agent instance.
Type Parameters
The type returned by
consume(). When the input includes a resolveResult function, consume() awaits it after the stream finishes and returns the value.
