{"slug": "ironcurtain-a-secure-runtime-for-autonomous-ai-agents", "title": "IronCurtain – A secure* runtime for autonomous AI agents", "summary": "IronCurtain is a research prototype runtime that enforces security policies for autonomous AI agents using a human-readable constitution. The system compiles natural-language rules into deterministic policies, assuming the LLM may be compromised, and mediates all agent actions through MCP servers with allow/deny/escalate decisions. It aims to provide a secure alternative to ambient authority in agent frameworks.", "body_md": "**A secure* runtime for autonomous AI agents, where security policy is derived from a human-readable constitution.**\n\n**When someone writes \"secure,\" you should immediately be skeptical. What do we mean by secure?*\n\nWarning\n\n**Research Prototype.** IronCurtain is an early-stage research project exploring how to make AI agents safe enough to be genuinely useful. APIs, configuration formats, and architecture may change. Contributions and feedback are welcome.\n\nThe agent is asked to clone a repository and push changes. Both `git_clone`\n\nand `git_push`\n\nare escalated by the policy engine, but the auto-approver approves them automatically — the user's trusted input from command mode (Ctrl-A) provided clear intent, so no manual `/approve`\n\nwas needed.\n\nAutonomous AI agents can manage files, run git commands, send messages, and interact with APIs on your behalf. But today's agent frameworks give the agent the same privileges as the user such as full access to the filesystem, credentials, and network. Security researchers call this **ambient authority**, and it means a single prompt injection or multi-turn drift can cause an agent to delete files, exfiltrate data, or push malicious code.\n\nThe common response is to either restrict agents to a narrow sandbox (limiting their usefulness) or to ask the user to approve every action (limiting their autonomy). Neither is satisfactory.\n\nIronCurtain takes a different path: **express your security intent in plain English, then let the system figure out enforcement.**\n\nYou write a **constitution** which is a short document describing what your agent is and isn't allowed to do. IronCurtain compiles this into a deterministic security policy using an LLM pipeline, validates the compiled rules against generated test scenarios, and then enforces the policy at runtime on every tool call. The result is an agent that can work autonomously within boundaries you define in natural language.\n\nThe key ideas:\n\n**The agent is untrusted.** IronCurtain assumes the LLM may be compromised by prompt injection or drift. Security does not depend on the model \"being good.\"**English in, enforcement out.** You write intent (\"no destructive git operations without approval\"); the system compiles it into deterministic rules that are enforced without further LLM involvement at runtime.**Semantic interposition.** Instead of giving the agent raw system access, all interactions go through[MCP](https://modelcontextprotocol.io/)servers (filesystem, git, etc.). Every tool call passes through a policy engine that can**allow**,** deny**, or** escalate**to the user for approval.** Defense in depth.**Agent code runs in a V8 isolate with no direct access to the host. The only way out is through semantically meaningful MCP tool calls and every one is checked against policy.\n\nIronCurtain supports two session modes with different trust models:\n\n-\n**Builtin Agent (Code Mode)**— IronCurtain's own LLM agent writes TypeScript snippets that execute in a V8 sandbox. IronCurtain controls the agent, the sandbox, and the policy engine. Every tool call exits the sandbox as a structured MCP request, passes through the policy engine (allow / deny / escalate), and only then reaches the real MCP server. -\n**Docker Agent Mode**— An external agent (Claude Code, Goose, etc.) runs inside a Docker container with no network access. IronCurtain mediates the external effects: LLM API calls pass through a TLS-terminating MITM proxy (host allowlist, fake-to-real key swap), MCP tool calls pass through the same policy engine, and package installations (npm/PyPI) go through a validating registry proxy.\n\nIn both modes, the agent is **untrusted**. Security does not depend on the model following instructions — it is enforced at the boundary.\n\nSee [SANDBOXING.md](/provos/ironcurtain/blob/master/SANDBOXING.md) for the full architecture with diagrams, layer-by-layer trust analysis, and macOS platform notes.\n\n- Node.js 22, 24, or 26 — the even-numbered major lines IronCurtain tests (required by\n`isolated-vm`\n\n; 24 and 26 install prebuilt binaries, Node 22 compiles from source at install and needs a C/C++ toolchain). Odd-numbered lines (23, 25) run but are untested —`ironcurtain doctor`\n\nwarns. - Docker — not required but\n**strongly recommended** for Docker Agent Mode, which provides the strongest isolation. On macOS 26+ (Apple silicon),[Apple](https://github.com/apple/container)works as an alternative backend (VM per container; used automatically when its services are running — see`container`\n\n`containerRuntime`\n\nin`ironcurtain config`\n\n) - An API key for at least one LLM provider (Anthropic, Google, or OpenAI)\n\n**As a global CLI tool (end users):**\n\n```\nnpm install -g @provos/ironcurtain\n```\n\n**From source (development):**\n\n```\ngit clone https://github.com/provos/ironcurtain.git\ncd ironcurtain\nnpm install\n```\n\n**1. Set your API key:**\n\n```\nexport ANTHROPIC_API_KEY=sk-ant-...\n```\n\nYou can also place keys in a `.env`\n\nfile in the project root (loaded automatically via `dotenv`\n\n), or add them to `~/.ironcurtain/config.json`\n\nvia `ironcurtain config`\n\n. Environment variables take precedence over config file values. Supported: `ANTHROPIC_API_KEY`\n\n, `GOOGLE_GENERATIVE_AI_API_KEY`\n\n, `OPENAI_API_KEY`\n\n.\n\n**2. Run the first-start wizard** (run this explicitly before using the recommended mux path; it also runs automatically on first non-mux `ironcurtain start`\n\n):\n\n```\nironcurtain setup\n```\n\nWalks you through GitHub token setup, web search provider, model selection, and other settings. Creates `~/.ironcurtain/config.json`\n\nwith your choices.\n\nIronCurtain ships with a default policy geared towards the developer experience — read-only operations are allowed, mutations (writes, pushes, PR creation) escalate for human approval. You can start using it immediately after setup.\n\nThe recommended way to use IronCurtain. It gives you the full power of your agent's interactive TUI (Claude Code or Goose) while IronCurtain mediates every tool call through its policy engine — all in a single terminal.\n\n```\nironcurtain mux\n```\n\n**Key capabilities:**\n\n**Full agent TUI**— The agent runs in a PTY inside a Docker container with no network access. You interact with it exactly as if it were running locally.**Inline escalation handling**— When a tool call needs approval, an escalation picker overlays the viewport with single-key actions (a/d/w for approve/deny/whitelist). Use`/approve+ N`\n\nto whitelist a domain or path for the rest of the session.**Trusted user input**— Text typed in command mode (Ctrl-A) is captured on the host side before entering the container. This creates a verified intent signal that the auto-approver can use — e.g., typing \"push my changes to origin\" will auto-approve a subsequent`git_push`\n\nescalation.**Tab management**— Spawn multiple concurrent sessions (`/new`\n\n), switch between them (`/tab N`\n\n, Alt-1..9), close them (`/close`\n\n). Multiple mux instances can run in parallel.\n\nSee [DEVELOPER_GUIDE.md](/provos/ironcurtain/blob/master/DEVELOPER_GUIDE.md) for the full walkthrough: input modes, trusted input security model, escalation workflow, and keyboard reference.\n\nUse `ironcurtain start`\n\nfor quick one-shot tasks, scripts, or when you explicitly want the local builtin agent. For normal interactive Docker-agent work, use `ironcurtain mux`\n\n.\n\n```\nironcurtain start \"Summarize the files in ./src\"     # Single-shot mode\nironcurtain start -w ./my-project \"Fix the tests\"    # Single-shot workspace mode\nironcurtain start --agent builtin                    # Local builtin REPL, no Docker\nironcurtain start --persona my-assistant \"Check my email\"  # Use a persona\n```\n\nIronCurtain also supports session resume (`--resume <session-id>`\n\n), a legacy raw PTY/debug mode, a Signal messaging transport for mobile approval, and a daemon mode for scheduled cron jobs. The daemon has an optional [web UI](/provos/ironcurtain/blob/master/DAEMON.md#web-ui) (`--web-ui`\n\n) for browser-based monitoring and escalation handling. See [RUNNING_MODES.md](/provos/ironcurtain/blob/master/RUNNING_MODES.md) for details.\n\nIronCurtain orchestrates multiple AI agents through structured workflows. The bundled **vulnerability discovery** workflow hunts memory-safety and logic bugs in native code through a tiered harness pipeline (Tier 1 isolated function → Tier 2 multi-component → Tier 3 full build) with libFuzzer/AFL++ coverage gating, hypothesis-driven `discover`\n\n/`triage`\n\nstates, and a final human report-review gate. The **design-and-code** workflow runs plan / design / implement / review cycles, also with human gates. Each agent runs in its own Docker container with role-specific policy boundaries; the engine manages state transitions, artifact passing, and crash-resume checkpointing automatically. Open source, runs entirely on your machine, enforces per-agent security policies via the constitution-based policy engine, and works with any Docker-containerized agent — comparable in scope to Amazon Kiro and Google Jules for coding tasks, but with first-class security and an extensible workflow definition format.\n\n**The web UI is the intended interface for workflow runs.** Start the daemon, open the printed URL, and drive runs from the Workflows page — the state-machine graph above is live, the agent-message timeline streams with markdown rendering, gate reviews include a workspace + artifact browser, and past runs stay listed.\n\n```\nironcurtain daemon --web-ui\n```\n\nCLI access is available for scripting, automation, and debugging:\n\n```\nironcurtain workflow start vuln-discovery \\\n  \"Find memory-safety bugs in libical\" --workspace ~/src/libical\nironcurtain workflow start design-and-code \\\n  \"Build a REST API with authentication\"\n```\n\nSee [WORKFLOWS.md](/provos/ironcurtain/blob/master/WORKFLOWS.md) for the full documentation.\n\nThe default policy works well for general development, but you can tailor it to your workflow:\n\n**1. Customize your constitution** (optional but recommended):\n\n```\nironcurtain customize-policy\n```\n\nAn LLM-assisted conversation that generates a constitution tailored to your workflow, saved to `~/.ironcurtain/constitution-user.md`\n\n. You can also edit this file directly.\n\n**2. Compile the policy:**\n\n```\nironcurtain compile-policy\n```\n\nTranslates your constitution into deterministic rules, generates test scenarios, and verifies them. Compiled artifacts go to `~/.ironcurtain/generated/`\n\n.\n\nPersonas are named policy profiles — each bundles a constitution, compiled policy, persistent workspace, and semantic memory. Use them to run agents with different roles or access levels.\n\n```\nironcurtain persona create my-assistant    # Create a persona\nironcurtain persona compile my-assistant   # Compile its policy\nironcurtain start --persona my-assistant \"Check my calendar\"\n```\n\nIn mux mode, `/new my-assistant`\n\nspawns a tab using that persona. Personas can also be assigned to cron jobs. See [DAEMON.md](/provos/ironcurtain/blob/master/DAEMON.md) for scheduled job configuration.\n\nPersonas can also be managed from the [web UI](/provos/ironcurtain/blob/master/DAEMON.md#persona-policy-management) — browse, create, edit constitutions, and compile policies with live progress. Because a policy is a security boundary, the web UI's mutation controls are read-only unless the daemon is started with `--allow-policy-mutation`\n\n(off by default).\n\nDrop SKILL.md packages under `~/.ironcurtain/skills/<name>/`\n\nto make purpose-specific guidance (helper scripts, deterministic checks, domain knowledge) available to every Docker agent session. The merged set is staged into a per-bundle host directory and bind-mounted **read-only** into the container at the path the active agent's native discovery walks — Claude Code is pointed at the staging dir via `--add-dir`\n\n, Goose scans `~/.config/goose/skills/<name>/SKILL.md`\n\n. The agent discovers them automatically and decides when to read them based on each skill's frontmatter description. The SKILL.md *format* is the open standard adopted by Claude Code, Goose, and Codex; only the *discovery path* differs per agent. Workflows can ship per-state skills inside the workflow package — see [WORKFLOWS.md](/provos/ironcurtain/blob/master/WORKFLOWS.md#skills).\n\nYou write intent in plain English; IronCurtain compiles it into deterministic rules:\n\n```\nconstitution.md → [Annotate] → [Compile] → [Resolve Lists] → [Generate Scenarios] → [Verify & Repair]\n                      │              │              │                  │                     │\n                      ▼              ▼              ▼                  ▼                     ▼\n              tool-annotations  compiled-policy  dynamic-lists   test-scenarios       verified policy\n                  .json            .json            .json            .json          (or build failure)\n```\n\n**Annotate**— Classify each MCP tool's arguments by role (read-path, write-path, delete-path, none).** Compile**— Translate the English constitution into deterministic if/then rules. Categorical references (\"major news sites\", \"my contacts\") are emitted as`@list-name`\n\nsymbolic references.**Resolve Lists**— Resolve symbolic lists to concrete values via LLM knowledge or MCP tool-use (e.g., querying a contacts database). Written to`dynamic-lists.json`\n\n, user-editable. Skipped when no lists are present.**Generate Scenarios**— Create test scenarios from the constitution plus mandatory handwritten invariant tests.** Verify & Repair**— Run scenarios against the real policy engine. An LLM judge analyzes failures and generates targeted repairs (up to 2 rounds). Build fails if the policy cannot be verified.\n\nAll artifacts are content-hash cached — only changed inputs trigger recompilation.\n\nA constitution clause like:\n\n```\n- The agent may perform read-only git operations (status, diff, log) within the sandbox without approval.\n- The agent must receive human approval before git push, pull, fetch, or any remote-contacting operation.\n```\n\ncompiles to:\n\n```\n[\n  { \"tool\": \"git_status\", \"decision\": \"allow\", \"condition\": { \"directory\": { \"within\": \"$SANDBOX\" } } },\n  { \"tool\": \"git_diff\", \"decision\": \"allow\", \"condition\": { \"directory\": { \"within\": \"$SANDBOX\" } } },\n  { \"tool\": \"git_push\", \"decision\": \"escalate\", \"reason\": \"Remote-contacting git operations require human approval\" }\n]\n```\n\nAny call that doesn't match an explicit `allow`\n\nor `escalate`\n\nrule is **denied by default**.\n\n```\nironcurtain annotate-tools --server filesystem   # Annotate one server (merge with existing)\nironcurtain annotate-tools --all                 # Re-annotate all servers\nironcurtain compile-policy                      # Compile constitution into rules and verify\nironcurtain refresh-lists                       # Re-resolve dynamic lists without full recompilation\nironcurtain refresh-lists --list major-news     # Refresh a single list\n```\n\nReview the generated `~/.ironcurtain/generated/compiled-policy.json`\n\n— these are the exact rules enforced at runtime.\n\nIronCurtain stores configuration and session data in `~/.ironcurtain/`\n\n:\n\n```\n~/.ironcurtain/\n├── config.json              # User configuration\n├── constitution.md          # User-local base constitution (overrides package default)\n├── constitution-user.md     # Your policy customizations (generated by customize-policy)\n├── generated/               # User-compiled policy artifacts (overrides package defaults)\n├── personas/                # Persona directories (constitution, policy, workspace, memory)\n├── skills/                  # User-global SKILL.md packages, mounted into every Docker session\n├── jobs/                    # Cron job definitions, workspaces, and run records\n├── sessions/\n│   └── {sessionId}/\n│       ├── sandbox/         # Per-session filesystem sandbox\n│       ├── escalations/     # File-based IPC for human approval\n│       ├── audit.jsonl      # Per-session audit log\n│       └── session.log      # Diagnostics\n└── workflow-runs/           # Shared-container workflow runs (see below)\n```\n\nSingle-session runs (`ironcurtain start`\n\n, mux tabs, cron jobs) write under `sessions/`\n\n. Shared-container workflow runs write under `workflow-runs/`\n\ninstead — see the next section.\n\nA workflow definition can opt in to a shared Docker container by setting `settings.sharedContainer: true`\n\nin its YAML. In that mode every agent state runs inside the same long-lived container and shares one policy engine instance; between states the orchestrator hot-swaps the active policy so each persona sees its own rules. All artifacts for the run land in a single tree:\n\n```\n~/.ironcurtain/workflow-runs/<workflowId>/\n├── audit.jsonl              # Persona-tagged append-only audit\n├── messages.jsonl           # Orchestrator message log\n├── workspace/               # Agent workspace (filesystem MCP root)\n├── bundle/                  # Shared container support (claude-state, orientation, sockets, escalations, system-prompt.txt)\n├── states/\n│   └── <stateId>.<visitCount>/   # session.log + session-metadata.json per invocation\n└── proxy-control.sock       # Coordinator UDS for policy hot-swap\n```\n\nNo per-session entries are created under `~/.ironcurtain/sessions/`\n\nfor a shared-container workflow run. User-visible commands (`ironcurtain workflow start|resume|inspect|list`\n\n) are unchanged. See [WORKFLOWS.md](/provos/ironcurtain/blob/master/WORKFLOWS.md) for authoring workflow definitions and the full lifecycle.\n\nEdit configuration interactively:\n\n```\nironcurtain config\n```\n\nKey configuration areas: models and API keys, resource budgets (token/step/time/cost limits), auto-approve escalations, web search provider, audit redaction, and memory server LLM settings. See [CONFIG.md](/provos/ironcurtain/blob/master/CONFIG.md) for the full reference.\n\nTo route LLM traffic through a gateway like LiteLLM or OpenRouter (in both Code Mode and Docker Agent Mode), see [MODEL_ROUTING.md](/provos/ironcurtain/blob/master/MODEL_ROUTING.md).\n\nRoute Docker agents through model-provider profiles (e.g. GLM-5.2 via OpenRouter, no sidecar) with `ironcurtain config`\n\n→ Model Providers, then pick a profile at `/new`\n\nor with `--provider-profile`\n\n— see [MODEL_ROUTING.md](/provos/ironcurtain/blob/master/MODEL_ROUTING.md#first-class-openrouter).\n\nIronCurtain ships with six pre-configured MCP servers. All tool calls (except memory) are governed by your compiled policy.\n\n| Server | Tools | Key capabilities |\n|---|---|---|\nFilesystem |\n14 | Read, write, edit, search files; directory tree; move; diff calculation |\nGit |\n28 | Full git workflow: status, diff, log, commit, branch, push/pull/fetch, clone, stash, blame |\nFetch |\n2 | HTTP GET with HTML-to-markdown conversion; web search (Brave, Tavily, SerpAPI) |\nGitHub |\n41 | Issues, PRs, code search, reviews via `ghcr.io/github/github-mcp-server` ; requires a GitHub personal access token |\nGoogle Workspace |\n128 | Gmail, Calendar, Drive, Docs, Sheets — requires OAuth setup via `ironcurtain auth` |\nMemory |\n5 | Persistent semantic memory with hybrid vector+keyword search, LLM summarization, and automatic compaction. Enabled for persona and cron sessions. |\n\nRead-only operations are allowed by default policy; mutations (writes, pushes, PR creation) escalate for human approval. Tools use `server.tool`\n\nnaming (e.g., `filesystem.read_file`\n\n, `memory.recall`\n\n). See [ADDING_MCP_SERVERS.md](/provos/ironcurtain/blob/master/ADDING_MCP_SERVERS.md) to add your own.\n\nIn Docker Agent Mode, the container has no network access — all traffic goes through IronCurtain's MITM proxy. By default, only LLM provider domains are reachable. The agent can request access to additional domains at runtime via the `proxy`\n\nvirtual MCP server (`add_proxy_domain`\n\n). Each request requires human approval via the escalation flow.\n\nApproved domains get a **raw passthrough tunnel** — HTTP, HTTPS, and WebSocket connections are forwarded without content inspection or credential injection. This gives the agent greater utility (calling third-party APIs, streaming data from external services) but means traffic to those domains is **unmediated**. See [SECURITY_CONCERNS.md](/provos/ironcurtain/blob/master/docs/SECURITY_CONCERNS.md) Section 2b-i for the threat model and [DEVELOPER_GUIDE.md](/provos/ironcurtain/blob/master/DEVELOPER_GUIDE.md) for usage details.\n\nIronCurtain is designed around a specific threat model: **the LLM goes rogue.** This can happen through prompt injection (a malicious email or web page hijacks the agent) or through multi-turn drift (the agent gradually deviates from the user's intent over a long session).\n\n**Filesystem containment**— Symlink-aware path resolution prevents path traversal and symlink-escape attacks.** Per-tool policy**— Each MCP tool call is evaluated against compiled rules. The policy engine classifies tool arguments by role (read-path, write-path, delete-path) to make fine-grained decisions.**Structural invariants**— Certain protections are hardcoded and cannot be overridden by the constitution: the agent can never modify its own policy files, audit logs, or configuration.**Human escalation**— When policy says \"escalate,\" the agent pauses and the user must explicitly approve or deny. Optionally, an LLM-based auto-approver handles unambiguous cases (see[CONFIG.md](/provos/ironcurtain/blob/master/CONFIG.md)).**Audit trail**— Every tool call and policy decision is logged to an append-only JSONL audit log.** Resource limits**— Token, step, time, and cost budgets prevent runaway sessions.\n\nThis is a research prototype. Known gaps include:\n\n**Policy compilation fidelity**— The LLM-based compiler can misinterpret constitution intent. The verification pipeline catches many errors but is not exhaustive. Always review the compiled`compiled-policy.json`\n\n.**V8 isolate boundaries**— Code Mode uses V8 isolates, not OS-level virtualization. A V8 zero-day could allow escape.** No outbound content inspection**— An agent allowed to write files could encode sensitive data to bypass content-level controls. Planned: LLM-based intelligibility checks on outbound content.**Escalation fatigue**— Too many false-positive escalations can lead to habitual approval. Tune your constitution to minimize unnecessary prompts.\n\nSee [docs/SECURITY_CONCERNS.md](/provos/ironcurtain/blob/master/docs/SECURITY_CONCERNS.md) for a detailed threat analysis.\n\n| Issue | Guidance |\n|---|---|\nMissing API key |\nSet the environment variable (`ANTHROPIC_API_KEY` , `GOOGLE_GENERATIVE_AI_API_KEY` , or `OPENAI_API_KEY` ) or add the corresponding key to `~/.ironcurtain/config.json` . |\nSandbox unavailable |\nOS-level sandboxing requires `bubblewrap` and `socat` . Install both, or set `\"sandboxPolicy\": \"warn\"` in your MCP server config for development. |\nBudget exhausted |\nAdjust limits in `~/.ironcurtain/config.json` under `resourceBudget` . Set any individual limit to `null` to disable it. |\nNode version errors |\nSupported Node.js lines are 22, 24, and 26 — the even-numbered major lines IronCurtain tests (`isolated-vm` ). 24 and 26 install prebuilt binaries; Node 22 compiles `isolated-vm` from source and needs a C/C++ toolchain. Odd-numbered lines (23, 25) are untested — `ironcurtain doctor` flags them with a warning rather than a hard failure. |\nPolicy doesn't match intent |\nReview `compiled-policy.json` to see the generated rules. Run `ironcurtain customize-policy` to refine your constitution, then `ironcurtain compile-policy` to recompile. Specific wording produces better rules — vague phrasing leads to vague policy. |\nAuto-approve not triggering |\nThe auto-approver only approves when the user's message explicitly authorizes the action (e.g., \"push to origin\" for `git_push` ). Vague messages always escalate to human review. Verify `autoApprove.enabled` is `true` in `config.json` . |\nPTY/mux terminal garbled after exit |\nRun `reset` in that terminal to restore normal mode. This is needed when the process is killed ungracefully and raw mode is not restored. |\nMux/listener: \"already running\" |\nOnly one mux or escalation-listener can run at a time. The lock at `~/.ironcurtain/escalation-listener.lock` is auto-cleared if the previous process is dead. If it persists, check the PID in the lock file. |\nSignal bot not responding |\nVerify the signal-cli container is running (`docker ps | grep ironcurtain-signal` ). Check that Signal is configured (`ironcurtain setup-signal` ). See\n|\n\n```\nnpm test                                    # Run all tests\nnpm test -- test/policy-engine.test.ts      # Run a single test file\nnpm test -- -t \"denies delete_file\"         # Run a single test by name\nnpm run lint                                # Lint\nnpm run build                               # TypeScript compilation + asset copy\n```\n\nSee [TESTING.md](/provos/ironcurtain/blob/master/TESTING.md) for the full testing guide, including integration test flags and conventions.\n\n```\nsrc/\n├── index.ts                    # Entry point\n├── cli.ts                      # CLI command dispatcher\n├── config/                     # Configuration loading, constitution, MCP server definitions\n├── session/                    # Multi-turn session management, budgets, loop detection\n├── sandbox/                    # V8 isolated execution environment\n├── trusted-process/            # Policy engine, MCP proxy, audit log, escalation handler\n├── pipeline/                   # Constitution → policy compilation pipeline\n├── escalation/                 # Escalation listener: session registry, TUI dashboard, state\n├── mux/                        # Terminal multiplexer: PTY bridge, renderer, trusted input\n├── persona/                    # Persona management (create, compile, resolve)\n├── memory/                     # Memory server integration (config, annotations, path resolution)\n├── signal/                     # Signal messaging transport (bot daemon, setup, formatting)\n├── daemon/                     # Unified daemon (Signal + cron scheduler, control socket)\n├── cron/                       # Cron job management (scheduler, job store, git sync, policy)\n├── docker/                     # Docker agent mode, PTY session, MITM proxy, registry proxy\n├── workflow/                   # Multi-agent workflow engine (orchestrator, state machine, gates)\n├── web-ui/                     # Web UI backend (JSON-RPC dispatch, event bus, workflow manager)\n├── servers/                    # Built-in MCP servers (fetch, web search providers)\n└── types/                      # Shared type definitions\npackages/\n└── memory-mcp-server/          # Standalone memory MCP server (publishable npm package)\n```\n\n", "url": "https://wpnews.pro/news/ironcurtain-a-secure-runtime-for-autonomous-ai-agents", "canonical_source": "https://github.com/provos/ironcurtain", "published_at": "2026-07-14 04:22:11+00:00", "updated_at": "2026-07-14 04:49:01.314977+00:00", "lang": "en", "topics": ["ai-safety", "ai-agents", "ai-infrastructure", "ai-policy"], "entities": ["IronCurtain", "MCP", "V8", "Docker", "Claude Code", "Goose"], "alternates": {"html": "https://wpnews.pro/news/ironcurtain-a-secure-runtime-for-autonomous-ai-agents", "markdown": "https://wpnews.pro/news/ironcurtain-a-secure-runtime-for-autonomous-ai-agents.md", "text": "https://wpnews.pro/news/ironcurtain-a-secure-runtime-for-autonomous-ai-agents.txt", "jsonld": "https://wpnews.pro/news/ironcurtain-a-secure-runtime-for-autonomous-ai-agents.jsonld"}}