This repo is a local-first blackbox CTF workspace powered by a native Claude Agent SDK loop. Public knowledge comes from Claude's WebSearch/WebFetch; local and run-specific evidence stays in the workspace and content-addressed artifact store.
repos/: legacy upstream knowledge submodules retained for historical review; not loaded by the runtimenotes/: historical design notesscripts/: run entrypoints and deterministic helper toolsweb_agent/: pure SDK runtime, session/artifact infrastructure, plus the optional governed runtimedocs/: architecture and iteration notes (init,pentagi)
File map:
mako/
README.md
SKILL.md
.env.example
docs/
init.md
pentagi.md
claude-sdk.md
runtime_claude_contract.md
web_agent/
claude_runtime.py
pure_sdk_agent.py
shared_session.py
session_ledger.py
followup.py
artifact_workspace.py
artifact_tools.py
cmd_agent.py
solver_shared.py
planner.py
deliberation.py
reflector.py
capability.py
logistics.py
task_interpreter.py
scripts/
run_web_agent.sh
followup.sh
tests/
test_deliberation.py
test_policy_control.py
test_structured_actions.py
docs/init.md: current baseline thinking after removing legacysync/docs/pentagi.md: PentAGI-driven integration notes and follow-up decisions- includes NYU Web smoke rerun notes (
2026-04-11) with intended-exploit verification and reliability-evaluation boundaries
- includes NYU Web smoke rerun notes (
docs/claude-sdk.md: Claude Agent SDK runtime, session, authentication, and retrieval boundariesdocs/runtime_claude_contract.md: completion and execution semantics used only by the optional governed runtime
- Create a virtual environment and install the runtime dependency:
cd mako
uv venv .venv
uv pip install --python .venv/bin/python -r requirements.txt- Create the environment file:
cp .env.example .env- If Claude CLI is already signed in, the default pure runtime needs no additional credential. For API or gateway authentication, edit
.envand set one credential plus any endpoint/model overrides:
ANTHROPIC_API_KEY=your_keyANTHROPIC_AUTH_TOKEN is the alternative for gateways that require bearer authentication. The optional governed runtime still requires an explicit credential and model.
Run the target directly:
./scripts/run_web_agent.sh "http://127.0.0.1:8080/" "Find SQL injection and retrieve flag"This launches one unrestricted Claude Agent SDK loop with Claude Code's default tools and system prompt under bypassPermissions. Mako does not select phases, validate commands, gate tool calls, inject planner actions, cap agent turns, or run its own executor. User/project/local Claude settings, Skills, plugins, MCP servers, and an existing Claude CLI login are discovered by the SDK defaults. Claude Code or organization-managed policies may still enforce their own native restrictions; pure mode adds no Mako restrictions on top.
The shared SDK session is stored at logs/claude_sdk_shared_context.json. Every invocation resumes that session when the endpoint/model/config identity matches, so tool results and conversation history remain available across runs. Run/session topology, call receipts, cost, turns, and terminal status are recorded separately in logs/mako_session_ledger.sqlite; the ledger does not copy the SDK transcript or maintain cognitive facts.
To deliberately start over, invoke the module with --new-session:
.venv/bin/python -m web_agent.pure_sdk_agent \
--target "http://127.0.0.1:8080/" \
--objective "Find SQL injection and retrieve flag" \
--new-sessionPure-run summaries are written under artifacts/mako/<run_id>/pure_sdk_run.json; they contain event types, tool names, artifact receipt references, usage, result text, and the session ID, but not tool inputs or SDK stderr.
Pure and follow-up runs share artifacts/mako/_evidence. Raw SDK tool results and ordinary files written under the run artifact directory are passively captured as immutable SHA-256 objects. Identical bytes share one object while each observation receives its own append-only provenance receipt containing run, session, call, tool, source kind, and source reference.
Mako exposes the following SDK-native MCP tools without changing Claude's permissions or action policy:
artifact_capture: explicitly preserve an existing file;artifact_list: list receipts from the current run;artifact_peek: read a bounded line range or literal-query result from a text artifact.
Binary artifacts return metadata only. Tool-use inputs are not persisted, Mako Artifact MCP results are not recursively captured, and every object is size/hash verified when read. The model decides if and when to use these tools; no artifact content is automatically injected into its prompt.
Continue the latest run without a planner or prompt rewrite:
./scripts/followup.sh --mode resume --message "Continue solving from the current evidence"The modes are:
inspect: ask the same session to explain or inspect its current work;resume: continue solving in the same session;fork: create a new SDK session from the selected run's recorded message checkpoint.
Pass --run-id <id> to target a non-latest run. Every follow-up creates an immutable child run and an intervention receipt. Forks record both run and session parentage; ordinary resume/inspect keeps the same session. Mako sends the operator message directly to the SDK and does not translate it into a plan or task.
Start the read-only web dashboard:
./scripts/dashboard.shOpen http://127.0.0.1:8765/ to inspect a Cairn-style provenance canvas: stated target/objective endpoints, run/session lineage, SDK calls, follow-up edges, grouped evidence receipts, token/cost totals, and run summaries. Clicking a node highlights its upstream/downstream lineage; the inspector has Detail, Evidence, and Log tabs. Replay reconstructs progress from stored timestamps, and Snapshot exports a timeline or JSON graph.
The dashboard is deliberately evidence/provenance-oriented rather than a fact/intent blackboard: it only reads logs/mako_session_ledger.sqlite, artifacts/mako/_evidence, and run-record JSON files under the project/artifact roots; it does not start agents, mutate run state, or infer cognitive facts from artifacts.
Use --port <port> to change the bind port, --host <host> to expose a different interface, and --open to launch a browser automatically:
./scripts/dashboard.sh --port 9000 --openThe previous interpreter/planner/validator runtime remains available for regression comparison and conservative runs:
MAKO_RUNTIME_MODE=governed \
./scripts/run_web_agent.sh "http://127.0.0.1:8080/" "Find SQL injection and retrieve flag"Governed architecture:
task_interpreterreadsobjective + hint + observed signals- interpreter writes
task_prior.*into shared sqlite memory - planner turns priors and runtime evidence into explicit subtasks
- solver deliberation reads:
- task priors
- active subtask
- persistent facts
- hypotheses
- reflection constraints
- controller reflection emits evidence-based policy advice
- the autonomy layer keeps semantic advice non-blocking by default while preserving hard execution and completion invariants
- in
claudemode, a single Claude tactical solver owns the next executable step - in
claude_collabmode, a counter-solver and corrector challenge that step before execution - capability manager evaluates execution gaps (
reuse existing actionvswrite helpervsinstall dependencyvsreplan) - logistics layer executes environment/setup work requested by capability resolution and records it outside challenge-step counting
- command output updates:
- facts
- reflection state
- hypothesis lifecycle
- plan patches for follow-up subtasks
claude_collab runs also write artifacts/.../<run_id>/claude_dialogue.jsonl, which records the counter-solver and tactical solver prompts/replies for post-run inspection.
12. interpreter/planner are refreshed periodically or after drift / repeated low-gain failure
Architecture diagram:
flowchart TD
U[User / Challenge<br/>target + objective + hint] --> I[Task Interpreter<br/>task_interpreter.py]
I -->|write task_prior.*| M[(Shared Memory<br/>SQLite)]
M --> P[Planner<br/>planner.py]
P -->|active subtask| S[Deliberation Layer<br/>recommender -> corrector -> judge]
S --> C[Capability Manager<br/>reuse -> helper -> install -> replan]
C --> L[Logistics Layer<br/>env setup / helper generation / tool supplementation]
L -->|final action/command| E[Executor / Local Environment<br/>curl / sqlmap / bash / ffuf]
E --> O[Observed Output<br/>stdout / stderr / timing]
O --> F[Fact Extractor<br/>extract_facts]
O --> R1[Execution Reflector<br/>reflect_step in solver_shared.py]
O --> R2[Policy Reflector<br/>reflector.py]
O --> H[Hypothesis Manager<br/>update_hypotheses]
O --> PP[Plan Patch<br/>build_plan_patch]
F -->|facts| M
R1 -->|reflect.*| M
R2 -->|controller.*| M
H -->|hypothesis.*| M
PP -->|plan.current| M
M -->|task_prior + plan + facts + hypotheses + reflection| P
M -->|active subtask + facts + reflection| S
Governed runtime stack:
task_interpreter -> planner -> Claude tactical solver
-> optional counter-solver / corrector
-> capability -> logistics -> executor
executor -> fact extraction / hypothesis updates / execution reflection / policy reflection
-> plan patch -> planner
adaptive is the default autonomy mode. Planner actions, phase recommendations, controller families, semantic-recovery rules, and soft branch-shift requests are advisory: Claude may reject them when runtime evidence supports another route. Exact duplicate suppression, preflight validation, tool budgets, evidence-backed completion, and hard zero-gain circuit breakers remain enforced.
Use --autonomy-mode guarded (or the corresponding setting in .env.example) to restore blocking semantic policies. --force-debate adds the counter-solver/corrector around ordinary Claude runs; claude_collab always enables that debate. Runtime defaults and environment names are defined in .env.example.
Shared-memory data model:
task_prior.* -> interpreter-produced priors
facts -> runtime observations and extracted signals
reflect.* -> failure reason, strategy update, next-step constraints
plan.* -> current plan, active subtask title/phase/action hint
controller.* -> policy reflection outputs (must_do / must_avoid / clusters)
hypothesis.* -> candidate / confirmed / weak_candidate / rejected
run.* -> challenge-step and capability-step counters
events -> compact execution trace
flows -> run-level status
tasks_state -> objective-level execution status
subtasks_state -> step-level execution status and outcome
The authoritative environment-variable list is .env.example. The generation model is selected with:
ANTHROPIC_MODEL=your-modelThe default pure runtime delegates the full agent loop and tool execution to claude-agent-sdk. In governed mode, SDK built-in tools remain disabled and Mako retains command validation/execution; its per-role session IDs are stored separately from the pure shared session.
Main modules:
web_agent/pure_sdk_agent.py,web_agent/shared_session.py,web_agent/session_ledger.py,web_agent/followup.py,web_agent/artifact_workspace.py,web_agent/artifact_tools.pyweb_agent/claude_runtime.pyweb_agent/task_interpreter.pyweb_agent/planner.pyweb_agent/deliberation.pyweb_agent/capability.pyweb_agent/logistics.pyweb_agent/reflector.pyweb_agent/solver_shared.py,web_agent/cmd_agent.py
The governed execution workflow is phase-based:
- recon
- probe
- exploit
- extract
- verify
- summarize and save run log to
logs/cmd_agent_last_run.json
Memory database:
- default path:
logs/agent_memory.sqlite - shared by interpreter and solver under one
run_id - stores:
task_prior.*- extracted
facts reflect.*hypothesis.*
- designed to be vuln-agnostic (not SQL-only)
Control policy:
- phase state remains observable as
recon -> probe -> exploit -> extract -> verify, but is advisory inadaptivemode - interpreter priors and planner subtasks provide discussion context rather than command authority
- the tactical solver may agree with, adapt, or reject the active subtask's suggested action
- reflector/controller outputs guide replanning; only hard evidence-free-loop thresholds force a branch shift in
adaptivemode - action policy keeps semantic and controller rules modular and can restore blocking behavior through
guardedmode - failure reasons are normalized and mapped to canonical failure clusters
- capability acquisition is a separate loop and does not consume challenge-step budget
- each step records an
info_gainscore from newly discovered facts - each step generates a
reflection - hypotheses are explicitly tracked as:
candidateconfirmedweak_candidaterejected
Interpreter behavior:
- converts
description + shown informationintotask_prior - identifies likely challenge family and tech stack
- proposes:
- primary hypotheses
- secondary hypotheses
- deprioritized routes
- exploit chain candidates
- warns about weak routes without preventing evidence-backed exploration in
adaptivemode
Deliberation behavior:
- the Claude tactical solver proposes one executable step for the active subtask
- planner action hints remain advisory in
adaptivemode - counter-solver/corrector review runs only when explicitly requested or in
claude_collab - execution results are written back into memory
- reflection and planner patches update subsequent subtasks
- supports structured actions for brittle execution chains:
http_probe_with_baselineextract_html_attack_surfacecookiejar_flow_fetchservice_recovery_probemultipart_upload_with_known_actionbuild_jsp_wartomcat_manager_read_file
Capability and logistics behavior:
- capability resolution detects whether the chosen proposal lacks a required tool or dependency
- capability scoring prefers:
- existing structured action
- generated helper script
- controlled install
- replan
- logistics strategy selection is model-driven (
pipvssystem_package_managervsskip_install) with deterministic safety fallback - logistics executes support work for the chosen option
- logistics work is tracked as
capability_stepsand does not consumechallenge_steps - install targets are dynamic (not a fixed allowlist), but install timing is constrained by capability-policy and step accounting
-
Q: What does "mako" mean in this project?
-
A:
makorefers to Hitachi Mako (常陆茉子) and has no other meaning. -
问:这个项目里的 “mako” 是什么意思?
-
答:
mako指的是常陆茉子,除此之外没有任何含义。 -
質問:このプロジェクトにおける「mako」は何を意味しますか?
-
回答:
makoは常陸茉子を指し、それ以外の意味はありません。