Agent Mode
Agent mode lets AI coding assistants and automation tools drive the Olympix CLI programmatically through a structured JSON protocol over stdin/stdout.
Overview
Section titled “Overview”When --agent (or -am) is passed to any command, the CLI:
- Emits structured JSON events to stdout, one JSON object per line (NDJSON)
- Reads JSON commands from stdin, one per line
- Writes structured results to
.opix/agent/in the workspace directory - Suppresses interactive prompts and TUI rendering
- Routes all human-readable log output to stderr, keeping stdout a clean JSON stream
This makes it possible for tools like Claude Code, Cursor, GitHub Copilot, or custom scripts to run Olympix analyses, respond to prompts, and consume results without human interaction.
Enabling Agent Mode
Section titled “Enabling Agent Mode”Add --agent (or -am) to any command:
# BugPocer in agent modeolympix bug-pocer --agent
# Unit testing in agent modeolympix unit-testing --agent
# Mutation testing in agent modeolympix mutation-testing --agent
# Fuzz testing in agent modeolympix generate-fuzz-tests -p src/Vault.sol --agentolympix connect-fuzz-session -s <session-id> --agent
# Static analysis in agent modeolympix static-analysis --agent
# List all sessions (agent mode only)olympix sessions --agenttui, theme, login, login-sso and the org-* commands have no agent protocol — they ignore --agent and stay interactive.
Alternatively, set the environment variable:
export OLYMPIX_AGENT_MODE=1olympix bug-pocerJSON Protocol
Section titled “JSON Protocol”Events (CLI → Agent)
Section titled “Events (CLI → Agent)”Every line the CLI writes to stdout is a JSON object with this shape:
{ "event": "<event_type>", "data": { }, "actions": ["action1", "action2"]}| Field | Type | Description |
|---|---|---|
event | string | Event type identifier |
data | object, string, or null | Event-specific payload |
actions | string[] or null | Valid actions the agent may send next |
Commands (Agent → CLI)
Section titled “Commands (Agent → CLI)”Send one JSON object per line to stdin:
{ "action": "<action_name>", "data": { }}| Field | Type | Description |
|---|---|---|
action | string | The action to perform (must be one of the advertised actions) |
data | object or null | Action-specific payload |
disconnect is always a valid action at any prompt — it gracefully closes the connection and exits.
Common Events
Section titled “Common Events”| Event | Description | Data |
|---|---|---|
progress | Status update | { "message": "...", "percent": 42 } |
error | Error occurred | { "message": "...", "expected_actions": [...] } |
completed | Operation finished with nothing further to do | A message string (e.g. no eligible files / all contracts mercy-ruled) |
Static Analysis Agent Protocol
Section titled “Static Analysis Agent Protocol”Both analyze and static-analysis run a fresh scan in agent mode. static-analysis skips its interactive session picker rather than reconnecting to a previous run, so the two commands behave identically here.
olympix analyze -w . --agentolympix static-analysis -w . --agentEvent: findings_ready — reuses the BugPocer findings shape, with the verdict and PoC fields defaulted to "n/a" and session_id null:
{ "event": "findings_ready", "data": { "session_id": null, "findings": [ { "id": "f1", "title": "unchecked-return-value", "severity": "High", "description": "...", "affected_code": "...", "file_path": "src/Vault.sol", "line_number": 42 } ] }}The CLI exits 0 straight after emitting the findings — no action is required. Findings you have ignored in opix.config.json are filtered out before the event is emitted. A workspace with no Solidity files emits an error event and exits non-zero.
BugPocer Agent Protocol
Section titled “BugPocer Agent Protocol”BugPocer’s multi-stage pipeline maps to the following event/action sequence.
bug-pocer starts at session selection. start-bp-session skips sessions_list/new_session and begins directly at step 2 (scope_review, or diff_review in diff mode); the rest of the flow is identical and it accepts the same --diff-base/--diff-target flags.
1. Session Selection
Section titled “1. Session Selection”Event: sessions_list
{ "event": "sessions_list", "data": { "sessions": [ { "id": "abc-123", "title": "My Scan", "status": "ValidationRequested", "created_at": "...", "error_message": null } ] }, "actions": ["new_session", "connect_session", "disconnect"]}Actions:
new_sessionwith optional{ "title": "My scan" }— start a new scanconnect_sessionwith{ "session_id": "abc-123" }— reconnect to an existing session
1.5 Context Cache Review (conditional)
Section titled “1.5 Context Cache Review (conditional)”Event: context_cache_review — emitted only when a prior context matches this codebase and --rebuild-context was not passed.
{ "event": "context_cache_review", "data": { "match_type": "exact", "source_session_id": "def-456", "cached_at": "2026-07-01T12:00:00Z", "overlap_percent": 100, "changed_files": [], "changed_files_total": 0, "summary": {} }, "actions": ["reuse_context", "rebuild_context", "disconnect"]}Actions:
reuse_context— reuse the cached context (exact match) or seed context building from it (partial match)rebuild_context— ignore the cache and build a fresh context
match_type is exact (identical source fingerprint) or partial (overlap_percent ≥ 80). Closing stdin without answering defaults an exact match to reuse. See Context Cache for the rules.
2. Scope Review
Section titled “2. Scope Review”Event: scope_review
{ "event": "scope_review", "data": { "contracts": [ { "name": "Vault", "file": "src/Vault.sol", "functions": [{ "name": "withdraw", "visibility": "public" }] } ], "libraries": [] }, "actions": ["select_scope", "confirm_all", "disconnect"]}Actions:
confirm_all— scan the full inferred scopeselect_scopewith{ "exclude_contracts": [...], "exclude_libraries": [...], "exclude_functions": [...], "additional_docs": { "notes": "...", "links": [...] } }— narrow the scope
3. Validation Items
Section titled “3. Validation Items”Event: validation_item — sent one at a time
{ "event": "validation_item", "data": { "key": "identity", "name": "Project Identity", "confidence": 85, "content": "DeFi lending protocol...", "options": [ { "id": "opt1", "label": "Alternative 1", "value": "..." } ], "current": 1, "total": 7 }, "actions": ["confirm_item", "reject_item", "select_option", "disconnect"]}Actions:
confirm_item— accept the inferencereject_itemwith{ "explanation": "custom correction" }— provide a correctionselect_optionwith{ "option_id": "opt1" }— pick a suggested alternative
4. Security Questions
Section titled “4. Security Questions”Event: security_question
{ "event": "security_question", "data": { "question_id": "q1", "category": "trust_boundaries", "is_required": true, "priority": 1, "question_text": "Who are the trusted operators?", "context": null, "suggested_answers": [ { "id": "a1", "label": "Only owner", "value": "...", "show_follow_up_ids": [] } ], "current": 1, "total": 5, "is_follow_up": false, "parent_question_id": null }, "actions": ["select_answer", "custom_answer", "skip_question", "disconnect"]}Actions:
select_answerwith{ "question_id": "q1", "answer_id": "a1" }— pick a suggested answercustom_answerwith{ "question_id": "q1", "answer": "free text" }— provide your own answerskip_question— skip an optional question
5. Additional Documentation Prompt
Section titled “5. Additional Documentation Prompt”Event: additional_docs_prompt
{ "event": "additional_docs_prompt", "data": { "message": "Attach additional documentation..." }, "actions": ["submit_docs", "skip_docs", "disconnect"]}Actions:
submit_docswith{ "notes": "...", "links": [...] }— submit docs and start the scanskip_docs— start the scan without additional docs
6. Results
Section titled “6. Results”Event: initial_scan_completed
{ "event": "initial_scan_completed", "data": { "session_id": "abc-123", "message": "Scan complete", "total_scan_cost": "150 credits" }}Event: findings_ready
{ "event": "findings_ready", "data": { "session_id": "abc-123", "findings": [ { "id": "f1", "title": "Reentrancy in withdraw()", "severity": "High", "description": "...", "affected_code": "...", "file_path": "src/Vault.sol", "line_number": 42, "bugpocer_verdict": "true_positive", "user_verdict": "unreviewed", "user_verdict_reason": null, "effective_verdict": "true_positive", "confidence_score": 90, "poc_summary": "...", "poc_content": "..." } ] }, "actions": ["set_verdict", "generate_pdf", "save_pocs", "save_findings_md", "disconnect"]}When findings arrive, the CLI auto-downloads the PoC exploit files and the split findings markdown to .opix/agent/<session-id>/ (default filter: true positives + unverified). The actions let you re-export or query:
save_pocs— re-export PoCs →pocs_saved{ "session_id", "saved_count", "output_path" }save_findings_md— re-export markdown →findings_saved{ "session_id", "files": [{ "category", "count", "path" }] }generate_pdf— generate the PDF report →pdf_generated{ "session_id", "pdf_path" }set_verdictwith{ "finding_id": "f1", "verdict": true, "reason": "confirmed" }— record your user verdict (true= true positive,false= false positive,null= clear to unreviewed) →verdict_set
Killing a Session
Section titled “Killing a Session”kill-bp-session terminates an active session. It is a one-shot command — the session ID is passed as a flag and no stdin input is needed:
olympix kill-bp-session -s <session-id> --agentEvent: session_killed
{ "event": "session_killed", "data": { "session_id": "abc-123", "was_running": true }}was_running is false when the session was not running (e.g. already completed). A missing session ID or no acknowledgment within 30 seconds emits an error event and exits non-zero.
Test Generator Agent Protocol
Section titled “Test Generator Agent Protocol”unit-testing, mutation-testing, generate-unit-tests and generate-mutation-tests share the session / file-selection flow. Fuzz generation follows a different, dispatch-only flow — see Fuzz Test Generator Agent Protocol.
Session & file selection
Section titled “Session & file selection”sessions_list (actions new_session, connect_session, disconnect) works as above. Starting a new session emits:
Event: file_selection
{ "event": "file_selection", "data": { "command": "generate-unit-tests", "files": ["src/Token.sol", "src/Vault.sol"], "max_files": 10 }, "actions": ["select_files"]}Respond with select_files and { "selected": ["src/Token.sol"] }.
Dispatch receipt
Section titled “Dispatch receipt”Generation runs asynchronously and results are delivered by email; the CLI confirms dispatch with:
Event: results_ready
{ "event": "results_ready", "data": { "type": "unit_test", "session_id": "abc-123", "message": "unit test generation started. Check email for results." }, "actions": ["disconnect"]}If a run has nothing to generate (e.g. the selected contracts have no matching OlympixUnitTest test file, or all subject contracts were mercy-ruled), the CLI emits a terminal completed event with an explanatory message instead — a valid, non-error outcome.
Fetching results
Section titled “Fetching results”Reconnecting to a finished session (connect_session) fetches and downloads results:
Event: unit_test_results
{ "event": "unit_test_results", "data": { "session_id": "abc-123", "total_files": 4, "successful_files": 3, "branches_coverage": 72.5, "test_files": [ { "subject_contract": "Vault", "subject_path": "src/Vault.sol", "test_contract": "VaultTest", "test_path": "test/Vault.t.sol", "has_new_tests": true, "coverage_before": 40.0, "coverage_after": 72.5, "passed": 12, "failed": 0 } ] }}Event: mutation_test_results
{ "event": "mutation_test_results", "data": { "session_id": "abc-123", "total_mutations": 50, "killed": 42, "survived": 8, "score_percentage": 84, "mutations": [ { "file": "src/Vault.sol", "line": 42, "original": "...", "mutated": "...", "killed": true, "broken_tests": [] } ] }}The generated .t.sol test files are written into the workspace automatically.
Listing contracts
Section titled “Listing contracts”generate-unit-tests --list --agent emits list_contracts { "contracts": [{ "index", "name", "path" }] } and exits.
Fuzz Test Generator Agent Protocol
Section titled “Fuzz Test Generator Agent Protocol”Fuzz runs are long-lived. generate-fuzz-tests only dispatches the run and returns a session ID — full results are emailed and can be pulled back later with connect-fuzz-session.
# Dispatch a run (returns a session_id; results arrive by email)olympix generate-fuzz-tests -w . -p src/Vault.sol --agent
# List your fuzz sessionsolympix list-fuzz-sessions --agent
# Fetch a finished session's summary (+ optional PDF report)olympix connect-fuzz-session -s <session-id> --agent
# Session manager: list, then reconnect, in one processolympix fuzz-testing -w . --agentDispatching a run
Section titled “Dispatching a run”generate-fuzz-tests emits a progress event carrying the new session ID, then a terminal completed event:
{ "event": "completed", "data": { "type": "fuzz_test", "session_id": "abc-123", "message": "Fuzz generation started; results pending." }}Fetching results
Section titled “Fetching results”connect-fuzz-session (and connect_session from a session list) emits a summary of the finished run:
Event: fuzz_test_results
{ "event": "fuzz_test_results", "data": { "session_id": "abc-123", "contracts": 3, "strategies": 7, "test_cases": 128, "exploit_test_cases": 2 }, "actions": ["generate_report", "disconnect"]}generate_report— render the PDF report →pdf_generated{ "session_id", "pdf_path" }disconnect— exit without generating a report
If the run has not finished yet, the CLI emits results_ready { "type": "fuzz_test", "session_id", "message": "Results not ready yet…" } instead and exits.
Session manager
Section titled “Session manager”list-fuzz-sessions and fuzz-testing both emit sessions_list (actions new_session, connect_session, disconnect) and then follow the fetch flow above once you send connect_session.
File Output
Section titled “File Output”In agent mode, the CLI writes structured results to .opix/agent/ within the workspace:
.opix/agent/├── <session-id>/ # BugPocer, per session ("pending/" until the ID is known)│ ├── scope.json # Scope review data│ ├── diff.json # Diff review data (diff mode)│ ├── context-cache.json # Context cache review data│ ├── report.json # Initial scan report│ ├── findings.json # Findings (mirrors findings_ready)│ └── qa.json # Q&A exchange history├── bug-pocer/│ └── sessions.json # Session list├── unit-tests/│ ├── sessions.json # Session list│ ├── contracts.json # Available contracts│ └── results.json # Test results├── mutation-tests/│ ├── sessions.json # Session list│ └── results.json # Test results└── fuzz-tests/ ├── sessions.json # Session list └── results.json # Fuzz run summaryFiles are written atomically (temp file + rename) and use snake_case JSON.
Sessions Command
Section titled “Sessions Command”The sessions command is agent-mode-only and returns active sessions across all services in a single response:
olympix sessions --agentEvent: all_sessions — sessions grouped per service, as the arrays bug_pocer, unit_tests, mutation_tests, fuzz_tests and static_analysis. Each entry has id, title, status and created_at.
Error Handling
Section titled “Error Handling”Errors are emitted as error events:
{ "event": "error", "data": { "message": "Invalid data payload: ...", "expected_actions": ["select_scope", "confirm_all", "disconnect"] }}The expected_actions field tells you what the CLI is still waiting for. Re-send a valid action to continue — a malformed or invalid action is reported and re-prompted rather than terminating the session.
Timeouts
Section titled “Timeouts”While stdin stays open, the CLI does not give up on a slow agent: on an internal read timeout it re-emits the pending event and keeps waiting. It only ends a stage when it receives a valid action or when stdin is closed (EOF), at which point it disconnects and exits.
Disconnecting
Section titled “Disconnecting”Send { "action": "disconnect" } at any prompt to gracefully close the connection and exit. This is always a valid action.
Example: Full BugPocer Session
Section titled “Example: Full BugPocer Session”# Newline-delimited commands piped to stdinolympix bug-pocer --agent <<'EOF'{"action":"new_session"}{"action":"confirm_all"}{"action":"confirm_item"}{"action":"confirm_item"}{"action":"submit_docs","data":{"notes":"","links":[]}}EOFThe CLI emits context_cache_review (if a prior context matches), then scope_review (or diff_review in diff mode), then a validation_item for each inference, then (optionally) security_questions and the additional_docs_prompt, and finally initial_scan_completed / findings_ready. Respond to each with one of its advertised actions.
Need Help?
Section titled “Need Help?”If you encounter any issues or have questions, reach out:
Email: contact@olympix.ai