Documentation
¶
Overview ¶
Package aiagent provides a provider-agnostic, budgeted tool-calling agent loop for the autonomous-pentest engine. It sits one level above internal/aiassist: the ToolCaller interface normalizes the Anthropic Messages format (Anthropic + GLM) and the OpenAI chat-completions format (OpenRouter + OpenAI) into a single {assistant text + tool calls} shape, and Run drives that shape as a hard-budgeted loop against an injected ToolExecutor. All external dependencies (the model caller, the tool executor, and the wall clock) are interfaces so the loop is unit-testable with fakes — no real API calls and no real wall-clock in tests.
Index ¶
Constants ¶
const ( StoppedDone = "done" // model produced a final tool-less answer StoppedBudget = "budget" // a hard budget cap was hit StoppedCtx = "ctx" // the context was cancelled StoppedError = "error" // the ToolCaller or ToolExecutor returned an error )
Stop reasons for a completed run.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Budget ¶
type Budget struct {
MaxSteps int // max model turns
MaxToolCalls int // max total tool executions across the run
MaxTokens int // advisory token ceiling (0 = unlimited/untracked)
MaxWallMs int64 // max wall-clock milliseconds from run start
}
Budget bounds an agent run. A zero/negative value for any field means that dimension is unbounded. MaxTokens is best-effort (advisory): it is only enforced when the ToolCaller reports usage.
type Clock ¶
Clock is an injected time source so the loop's wall-clock budget is testable without a real clock. Production code passes RealClock; tests pass a fake.
type ErrNoToolSupport ¶
type ErrNoToolSupport struct{ Provider string }
ErrNoToolSupport is returned when the configured provider has no tool-calling path at all (so an agent run cannot proceed).
func (ErrNoToolSupport) Error ¶
func (e ErrNoToolSupport) Error() string
type Message ¶
type Message struct {
Role string
Text string
Calls []ToolCall // assistant messages: tool calls requested this turn
ToolCallID string // tool messages: the ToolCall.ID this result answers
}
Message is one entry in the running conversation history. Role is "user", "assistant", or "tool". For an assistant turn that requested tools, Calls holds the requested calls (so the ToolCaller can replay them to the provider in the correct wire format). For a tool-result message, ToolCallID ties the result back to the call that produced it.
type RunResult ¶
type RunResult struct {
FinalText string // the assistant's final text (best available if budget-stopped)
Steps int // model turns taken
ToolCalls int // tool executions performed
Tokens int // total tokens observed (best-effort)
Transcript []Message // the full message history, including seeded task and tool results
StoppedBy string // done | budget | ctx | error
}
RunResult summarizes a finished run.
func Run ¶
func Run(ctx context.Context, tc ToolCaller, exec ToolExecutor, system, task string, tools []ToolSpec, b Budget, clock Clock) (RunResult, error)
Run drives a budgeted tool-calling loop. It seeds the history with the task, then repeatedly: (1) checks hard budgets and ctx BEFORE each model turn, (2) asks the ToolCaller for one turn, (3) if the turn has no tool calls it is the final answer (StoppedDone), else executes each call via exec, appends the results, and checks budgets again after the batch.
Budget overruns are HARD stops: the loop transitions to StoppedBudget and, if it is cheap and still within remaining budget, does a final tool-less synthesis turn to surface a closing answer (mirroring the in-app agent's final-summary pass). Context cancellation yields StoppedCtx; a caller/executor error yields StoppedError with the error returned. On StoppedError, RunResult still carries the transcript accumulated so far.
type TokenUsage ¶
TokenUsage is best-effort per-turn token accounting.
func (TokenUsage) Total ¶
func (u TokenUsage) Total() int
Total returns input+output tokens for the turn.
type ToolCaller ¶
type ToolCaller interface {
Complete(ctx context.Context, system string, msgs []Message, tools []ToolSpec) (Turn, error)
}
ToolCaller runs one model turn. Complete is given the system prompt, the running message history, and the tools available this turn; it returns the assistant's text plus any tool calls. Implementations translate to/from a provider wire format but expose only this normalized shape.
func NewClientToolCaller ¶
func NewClientToolCaller(c *aiassist.Client) (ToolCaller, error)
NewClientToolCaller wraps an *aiassist.Client as a ToolCaller. It returns ErrNoToolSupport if the client's provider cannot run tool-calling loops.
type ToolExecutor ¶
ToolExecutor runs one tool call and returns its result string. A non-nil error is treated as a hard failure that aborts the run (StoppedBy "error"); tools that want to report a recoverable failure to the model should return it as the result string with a nil error.
type ToolSpec ¶
type ToolSpec struct {
Name string
Description string
Schema map[string]any // JSON Schema for the tool's input object
}
ToolSpec describes one tool made available to the model for a turn.
type Turn ¶
type Turn struct {
Text string
Calls []ToolCall
// Usage is best-effort token accounting reported by the provider (0 when the
// provider or transport does not surface it). MaxTokens budgeting is advisory
// and driven off this field.
Usage TokenUsage
}
Turn is one model turn: the assistant's text plus any tool calls it requested. When Calls is empty the turn is a final answer.