olium is the in-process AI agent runtime that powers every agentic feature in Vigolium. It ships as both:
- A user-facing command:
vigolium agent olium(aliases:vigolium olium,vigolium ol), for interactive chat in a TUI or scripted one-shot prompts. - A library:
pkg/olium/, that the autopilot, swarm, query, vigolium-audit-prep, and source-analysis paths all dispatch through. There are no subprocess SDK or ACP backends; every AI call in vigolium goes through this engine.
What it is
A turn-based, tool-using LLM agent written in Go. Components:What it does
Each invocation runs one multi-turn loop:- Append the user prompt to history.
- Stream a single provider response (text deltas, thinking deltas, tool calls).
- Append the assistant turn to history; emit
EventTurnDonewith token usage. - If there are no tool calls → emit
EventRunDoneand exit. - Otherwise dispatch the tool calls. If all calls are read-only the engine fans them out in parallel (cap = 8); otherwise it runs them strictly serially so writes can’t race reads. Tool results are appended to history in the model’s original order regardless.
- Loop back to step 2, capped by
MaxTurns(default 32 for chat / headless, 200 for autopilot).
- Tool result truncation / spill: results larger than
MaxToolResultBytes(default 16 KiB) get head+tail truncation with an elision marker. IfSpillDiris set (autopilot does this), the full payload spills to<SpillDir>/tool-results/and the model gets a head excerpt plus an on-disk path it canread_file. - Per-tool timeout: each tool invocation gets its own deadline (default 5 minutes). A runaway
bash curlcan’t hang the whole session. - Prompt caching: opt-in via
EnablePromptCache. Autopilot turns it on; the Anthropic providers writecache_control: ephemeralmarkers and the Codex OAuth provider writesprompt_cache_keyheaders, cutting repeated-prefix tokens by ~90 % across long runs.openai-api-key,openai-responses,openai-compatible(Ollama / OpenRouter / LM Studio / vLLM / Groq / …),anthropic-compatible, andgoogle-vertexdo not emit cache markers, so the flag is silently ignored for them. (anthropic-claude-sdk-bridgemanages caching inside the Claude Code Agent SDK.) - Skills: when a registry is loaded the engine injects an
<available_skills>block into the system prompt at construction, and registers aload_skilltool the model can call to fetch a skill body on demand.
Modes
Interactive TUI (default)
/:
/clear: clear conversation history./skill:<name> [args]: inline expansion of a loaded skill; the body is pasted into the prompt so the model doesn’t have to spend a tool call toload_skill.
One-shot non-interactive
Passing-p / --prompt runs a single prompt non-interactively and streams to stdout, the TUI is skipped automatically.
[turn done in= out= cached=] summaries go to stderr. Exits non-zero on engine error.
Library use (autopilot, swarm, query)
pkg/agent/olium_adapter.go is the single dispatch path every other agent feature funnels through:
runOliumPrompt(ctx, cfg, prompt, streamWriter, sourcePath): fresh engine per call.runOliumOnEngine(ctx, cfg, eng, prompt, streamWriter): reuses an engine so the conversation prefix stays warm (used by source-analysis to fork an explore phase into 3 parallel format calls).acquireProviderSlot(ctx, cfg): global semaphore (size =agent.olium.max_concurrent, default 4) that bounds in-flight provider calls process-wide so swarm phase fan-out can’t trigger 429s on tier-1 plans.EffectiveCallTimeout(): default 10 min per provider call; 0 → default, negative → no timeout.
Providers
Eleven drivers inpkg/olium/provider/. The provider ID is vendor-first so it’s obvious which credential field applies:
With no
--provider flag and no YAML override, vigolium defaults to openai-compatible with gemma4:latest against a local Ollama endpoint, so a freshly initialized config works out of the box without any cloud credentials. The anthropic-oauth provider also prepends a Claude Code preamble to the system prompt and adds the oauth-2025-04-20 beta header so it’s accepted on the same endpoint as anthropic-api-key.
Codex auth refreshes itself: it parses the JWT, checks expiry with a 60 s skew, and posts to /oauth/token with the stored refresh token, rewriting ~/.codex/auth.json (mode 0o600).
Note: the REST API falls back toagent.olium.*invigolium-configs.yaml(which keeps warm sessions and prompt caches stable across requests), but every agent run endpoint also accepts per-request BYOK credentials (api_key,oauth_token,oauth_cred_file,oauth_cred_json). The audit dispatcher additionally acceptsaudit_auth/piolium_authfor per-driver overrides.
Tools
Built-in tool registry, eight tools registered in this order:
*
web_fetch is only read-only in the no-capture variant (TUI chat / query, no DB wired). Under autopilot the capture-enabled variant persists every fetch as an http_record — http mode returns a record_uuid, browser mode captures every XHR/fetch during render (many records per call) — so it can issue state-changing methods, is not read-only, and does not join the parallel read-only fan-out (concurrent capturing fetches would race the shared record store).
The IsReadOnly() flag is what the engine uses to decide whether to fan out a turn’s tool calls in parallel. bash runs without an approval prompt (yolo mode), only the catastrophic-pattern guard prevents disasters.
Autopilot adds more
When the engine runs undervigolium agent autopilot, the registry also gets:
halt_scan: model-driven exit. Sets a halt signal; the run loop exits after the current turn.report_finding(legacy/shadow): persists a finding to the database and acceptsrecord_uuidslinking its provinghttp_records. Shadow mode also mirrors a candidate for independent grading. It soft-warns at 50 saved findings and hard-caps at 200.propose_candidate(enforced): persists a claim and its evidence for a fresh-context skeptic verifier. Only confirmed candidates are promoted to findings.load_skill: fetch a skill body by name (registered whenever the skill registry is non-empty).update_plan/remember: durable scratchpad plan + notes that survive section rotation and resume (registered unconditionally, seeded from the pipeline’s frozen plan when present).- Vigtool (registered when
Repois non-nil): scanner- and record-aware tools —- Scan / modules:
run_native_scan,run_module,run_extension,list_modules. - Record surface:
query_records,inspect_record,replay_request,send_raw_http. - OAST:
oast_poll,oast_mint. - Sessions / findings:
list_sessions,get_session,list_findings,update_finding. - Auth:
list_auth_sessions,auth_session_lookup,browser_auth(only whenagent-browseris on$PATH). - Payloads:
attack_kit. - Live Burp bridge (server runs, operator-enabled listener):
search_burp_items,inspect_burp_item. - Capture-enabled
web_fetch+browser_probereplace their built-in variants (needRepo+ProjectUUID), persisting every fetch as anhttp_record.
- Scan / modules:
attack_kitreturns a curated starter-payload set per attack class (xss,sqli,ssrf,cmd-injection,path-traversal,ssti,xxe,open-redirect,crlf) — read-only and non-mutating. Its SSRF Redis gopher PoC is a harmlessPINGprobe (v0.2.5 changed it from a destructiveFLUSHALL), so an autonomous agent can’t wipe a target’s data; intrusive commands are left to explicit operator authorization. Pair it withreplay_requestto actually send payloads.replay_requestsends a mutated stored record and persists the exact sent request + received response as anolium-replayhttp_record, returning its UUID asreplay_record_uuid— pass that toreport_findingorpropose_candidateviarecord_uuidsas reproducible proof.search_burp_items/inspect_burp_itemare read-only tools (server runs only) that search / inspect the live Burp Target site map or Proxy history over an operator-enabled read-only bridge listener; they never modify Burp.
Skills
Skills are Markdown workflow files with YAML frontmatter, following the agentskills.io convention so files written for Claude Code or pi work in olium verbatim. Format:name must match [a-z0-9-]+ (≤64 chars); description ≤1024 chars.
Discovery
The skill registry walks four scopes, first-found-by-name wins:- Project:
.agent/skills/and.claude/skills/in the working directory and every ancestor, closest first. - User:
~/.vigolium/skills/(only whenIncludeUserSkills=true). - Embedded: shipped in the binary under
public/presets/skills/viago:embed.
<root>/<name>/SKILL.md (directory skill, the agentskills.io standard) or <root>/<name>.md (single-file shorthand; frontmatter name must match the filename stem).
Generic chat (vigolium agent olium, headless) loads scopes 1 + 3 only. Autopilot and swarm load all three so security-specific workflows in ~/.vigolium/skills/ don’t pollute casual chat.
Use
The engine writes an<available_skills> block into the system prompt listing every skill’s name + description + location. The model fetches bodies on demand via the load_skill tool, progressive disclosure, so unused skills don’t burn tokens.
In the TUI, type /skill:<name> [args] to inline-expand a skill body into your prompt directly, no tool call needed.
CLI flags
-p/--prompt → stdin (auto-detected when piped, or forced with --stdin). Values flow CLI → YAML → env: every CLI flag falls back to its agent.olium.* YAML field, which in turn falls back to the documented default or env var.
Configuration
The fullagent.olium block:
autopilot_mode is legacy by default. shadow and enforced enable durable section rotation; enforced additionally gates finding promotion through a fresh-context verifier. A negative max_concurrent removes the provider-call cap, while 0 keeps the default cap of 4.
Adjacent config blocks worth knowing:
agent.sessions_dir: where per-run session directories go. Default~/.vigolium/agent-sessions/.agent.browser: togglesagent-browserintegration (the binaryweb_fetchshells out to inmode: browser).agent.audit: controls the optional vigolium-audit / piolium prep step that autopilot/swarm can stack ahead of the olium loop.
Sessions and on-disk state
Every agent run gets a session directory underagent.sessions_dir (default ~/.vigolium/agent-sessions/<run-uuid>/). Bare vigolium agent olium chat doesn’t write a session, it’s only autopilot/swarm/query that materialise one.
Inside a session dir you may find:
runtime.log: per-turn event log (text deltas, tool start/end, turn-done summaries).tool-results/<tool>-<call-id>.txt: spilled oversized tool outputs (when the engine’sSpillDiris set).session-config.json: run metadata (project / scan UUIDs, options).swarm-plan.json,master-output.md,audit-stream.jsonl,checkpoint.json, produced by the higher-level modes that wrap olium (swarm, vigolium-audit, autopilot).
vigolium agent session list / --full / --tail.
Stream events
The engine emits a unifiedEvent channel regardless of provider:
Token counts on
EventTurnDone are accumulated by every higher-level caller (autopilot for budget enforcement, the adapter for agenttypes.TokenUsage, the swarm for cost reporting).
When to use what
Olium itself is the general-purpose chat / dev surface and the engine every other mode reuses, it is not a security scan on its own.
See also
- Agent Mode, the full agent subcommand map.
- Autopilot, autonomous scan mode built on the olium engine.
- Swarm, AI-guided multi-phase scan that drives the native scanner.
- How It Works, provider list and the high-level dispatch story.
