This document is written for an LLM or automated agent driving Cortex. It
explains how to connect, authenticate, and use the API productively. The
running Agent always self-documents its full route list through
GET /tools and GET /openapi.json; this guide covers the workflow and the
conventions those manifests assume.
Cortex has two cooperating servers, both bound to 127.0.0.1 only:
| Component | Default port | Role |
|---|---|---|
| Agent (injected DLL) | 6969 |
Renderer hooks, overlay, breakpoints, live debugging, patches, calls, screenshots, prompts |
| Host (external exe) | 6970 |
Heavy memory scans from outside the process, so scan buffers never pollute the target |
Prefer the Host for scanning (/scan/*) and the Agent for anything
that touches the render loop, execution control, or the human overlay. Both
share one persistent per-target workspace (project.json).
Every non-public route requires the header X-Cortex-Token.
- The Agent reads or creates
cortex.tokennext to the DLL. - The Host writes
cortex_host.tokennext to its exe.
Read that file and send its contents as X-Cortex-Token on every request.
The only routes that need no token are /status, /health, /tools, and
/openapi.json.
GET /health— confirm the server is up.GET /tools— load the authoritative route manifest with parameter names. Always trust the exact field names from/tools; do not guess.GET /modules— get the target's module list (name, base, size). Resolve addresses relative to a module base, never to a raw absolute from a prior session.GET /project— recover named addresses, pointer paths, structures, and notes saved in earlier sessions. This is your long-term memory.
Cortex also speaks Model Context Protocol over POST /mcp (JSON-RPC 2.0).
The tool catalog is auto-derived from /tools, so there is no second registry
to maintain.
initializereturnsprotocolVersion "2024-11-05", capabilities, serverInfo.tools/listreturns MCP tool descriptors with aninputSchema.tools/callloops back through the same HTTP server; put path placeholders inarguments._pathand query params inarguments._query.- Batch (array) requests are supported.
The same X-Cortex-Token gates /mcp — one token for both surfaces.
- All request/response bodies are JSON unless a route returns binary data
(e.g.
/screenshotreturnsimage/png, or{image_base64}with?encoding=base64). - Numeric types for memory routes:
i8/i16/i32/i64,u8/u16/u32/u64,float,double,bytes(hex),string. - Addresses may be sent as hex strings (
"0x13B7161C") or numbers. module.ext+RVAform is accepted everywhere addresses are expected — either as a single string ("godfather2.exe+0x554820") or as an object ({"module":"godfather2.exe","rva":"0x554820"}). Cortex re-resolves the base at every call, so persisted scripts survive ASLR across sessions.- Prefer
module+RVAfor any address you plan to store, log, or send through/session/export. Cortex emitsaddress_namedfields in this form automatically. - Absolute addresses change on every restart. Persist a pointer path, an
AOB signature, or the
module+RVAform (via/project) so an address can be re-resolved later.
- Find a value — scan on the Host:
POST /scan/newwith the current value, play the game so the value changes, thenPOST /scan/nextwith the new value / a comparison filter (increased,decreased,changed,bigger,smaller,between, deltas). Repeat until few candidates remain. - Confirm — freeze a candidate (
POST /freeze) and check the effect in-game before trusting it. Convergence across scans is not proof; a freeze test is. - Persist — save the confirmed address under a name with
POST /project/address, or aPOST /project/pointer_pathif it moves. - Understand —
GET /disasm,/analysis/functions,/analysis/cfg,/analysis/xrefs,/analysis/vtable,/analysis/structureto map the code and structures around it. - Modify —
POST /memory/write,/patch/write,/patch/detour, orPOST /call/function. Every mutation is journaled; undo withPOST /actions/rollback.
Cortex works even when the game window is not focused or is minimized.
- Screenshots —
GET /screenshot?mode=autotries the render hook, thenPrintWindow(PW_RENDERFULLCONTENT), then a cached last frame. The response carries anX-Cortex-Capture-Sourceheader telling you which path served it. - Input transports —
os(Win32PostMessage, works in background),dinput(DirectInput synthesis for games that read the device directly),game(SendInput, foreground only). Pick per target. - Sequences —
POST /input/sequencequeues multi-step scripts. PollGET /input/sequence/{id}, cancel withDELETE /input/sequence/{id}. - Record/replay —
POST /input/record/startthen/stopreturns a sequence that can be re-fed into/input/sequence. - Window control —
GET /window,POST /window/{focus,restore,minimize,move}.
Every breakpoint may carry a capture array evaluated at each hit. Expressions
support registers, integers, +/-, and pointer-sized dereferences with []:
{
"capture": [
{ "name": "hp", "expression": "[[ecx+0x18]+0x4]", "type": "i32" },
{ "name": "name", "expression": "[ecx+0x40]", "type": "cstring", "size": 32 }
]
}Hit logs are paginated and non-destructive — page with
?since_seq=&limit= and watch dropped_entries + total_hits. Attach an
auto-trace with POST /debug/breakpoint/{id}/trigger (supports
stop_on_return to bound the trace to the current function).
Stack walks combine EBP chain → StackWalk64 → heuristic exec-page scan, so
optimized prologues still yield a call stack.
POST /network/capture { enabled: true } starts intercepting
recv/send/WSARecv/WSASend on ws2_32. Read the ring buffer with
GET /network/events?limit=.
POST /session/export writes a reproducible archive
(cortex_sessions/session_<UTC>/session.json + screenshot) with modules,
breakpoints (with paginated logs, captures, and module+RVA addresses), trace
metadata, and project state. Use it as a bug report or a diffable checkpoint.
When you need the person at the screen to act or report something the API
can't observe, use POST /prompt:
response_type: "ack"— a button the human presses when done.response_type: "number"/"text"— a value the human types back.timer_seconds— show a countdown (e.g. "take damage for 10s and tell me the total").
Then poll GET /prompt/{id} until status is answered or timeout.
Use GET /screenshot to see the result of an action — close the loop
visually rather than assuming a write had the intended effect.
- Arbitrary writes, patches, and native calls can crash the target. Prefer reversible operations and keep the action journal in mind.
/debug/breakpointcan freeze the game's threads until you continue (/debug/paused, then resume). Set the breakpointkindexplicitly.- Batch related operations with
POST /batch/runto reduce round trips; transactional batches roll back supported writes if a later step fails.