Architecture
April 17, 2026 · View on GitHub
Current Shape
ida-cli now has a runtime-adaptive middle layer instead of a single hard-coded IDA backend.
Layers
- Frontends
- Flat CLI
- MCP over stdio
- MCP over Streamable HTTP
- Router
- Spawns per-database workers
- Routes JSON-RPC requests
- Keeps active handle / per-path handle mapping
- Reuses workers when a path is already open
- Runtime Probe
- Detects the active IDA runtime
- Selects a worker backend before worker startup
- Prevents known crash paths from being entered blindly
- Worker Backends
native-linkedidat-compat
- Storage and caches
- Database cache:
~/.ida/idb/ - Response cache:
/tmp/ida-cli-out/ - Socket discovery:
/tmp/ida-cli.socket
Why This Matters
This split is the foundation for long-running RE server workloads:
- old runtimes and new runtimes no longer share one unsafe code path
- the router can evolve independently from backend implementation details
- IDA database caching is no longer tied to the source binary directory
- backend support can be declared and tested explicitly
Current Backends
native-linked
Used for runtimes that can safely open databases in-process through the vendored idalib line.
idat-compat
Used for older runtimes where the vendored idalib line would crash when opening databases.
This backend:
- shells out to
idat - runs short IDAPython snippets
- emits structured JSON back to the router
- reuses cached database artifacts in
~/.ida/idb/
Concurrency Model Today
Today the router model is:
- one server process
- many worker subprocesses
- one worker per open database handle
This already supports:
- multiple databases in parallel
- backend-specific worker behavior
- independent worker crashes without taking down the whole server
What Is Still Needed For “1000 Agents”
The current code is a strong base, but “1000 agents” needs another layer above the router:
- Request Gateway
- admission control
- auth / tenancy
- global rate limits
- Job Queue
- durable task scheduling
- retries
- cancellation
- fair sharing across users and binaries
- Worker Pool Manager
- warm workers
- backend-specific pools
- CPU / memory caps
- queue depth limits
- Cache Coordinator
- content-addressed database cache
- database lease / pinning
- result cache for expensive reads and decompilation
- Observability
- structured metrics per backend
- worker crash accounting
- slow-query tracing
Practical Upgrade Path
The recommended path from the current codebase is:
- Keep the current router as the local orchestration core.
- Move worker launch behind a queue / scheduler boundary.
- Make database cache ownership explicit and lease-based.
- Add capability-aware routing so unsupported methods never hit the wrong backend.
- Add backend smoke tests to CI for every supported runtime/backend pair.
Federation Skeleton
The codebase now includes a minimal federation status layer.
Set:
IDA_CLI_FEDERATION_CONFIG=/path/to/nodes.json
Example:
[
{
"name": "node-a",
"url": "http://127.0.0.1:9876",
"weight": 1,
"enabled": true
},
{
"name": "node-b",
"url": "http://127.0.0.1:9976",
"weight": 2,
"enabled": true
}
]
Current behavior:
- loads static node config
- probes
/healthzand/readyz - exposes federation node state through router status
This is a federation status and discovery skeleton, not yet a full remote execution fabric.
Validation
The repository now includes a 9.x compatibility verification script:
scripts/verify_9x_compat.py
It probes the selected backend and runs a worker-level compatibility pass for the currently declared idat-compat supported method set.