agentcage 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. agentcage-0.1.0/.github/workflows/publish.yml +18 -0
  2. agentcage-0.1.0/.github/workflows/test.yml +21 -0
  3. agentcage-0.1.0/.gitignore +11 -0
  4. agentcage-0.1.0/CHANGELOG.md +32 -0
  5. agentcage-0.1.0/CONTRIBUTING.md +31 -0
  6. agentcage-0.1.0/LICENSE +21 -0
  7. agentcage-0.1.0/PKG-INFO +399 -0
  8. agentcage-0.1.0/README.md +370 -0
  9. agentcage-0.1.0/SECURITY.md +18 -0
  10. agentcage-0.1.0/docs/agentcage.png +0 -0
  11. agentcage-0.1.0/docs/architecture.md +129 -0
  12. agentcage-0.1.0/docs/configuration.md +376 -0
  13. agentcage-0.1.0/docs/openclaw.md +186 -0
  14. agentcage-0.1.0/docs/security.md +122 -0
  15. agentcage-0.1.0/examples/basic/README.md +27 -0
  16. agentcage-0.1.0/examples/basic/agent/agent.js +73 -0
  17. agentcage-0.1.0/examples/basic/config.yaml +23 -0
  18. agentcage-0.1.0/examples/openclaw/README.md +11 -0
  19. agentcage-0.1.0/examples/openclaw/config.yaml +172 -0
  20. agentcage-0.1.0/pyproject.toml +53 -0
  21. agentcage-0.1.0/src/agentcage/__init__.py +0 -0
  22. agentcage-0.1.0/src/agentcage/cli.py +722 -0
  23. agentcage-0.1.0/src/agentcage/config.py +195 -0
  24. agentcage-0.1.0/src/agentcage/data/containers/Containerfile.dns +8 -0
  25. agentcage-0.1.0/src/agentcage/data/containers/Containerfile.helper +2 -0
  26. agentcage-0.1.0/src/agentcage/data/containers/Containerfile.proxy +11 -0
  27. agentcage-0.1.0/src/agentcage/data/patches/package-lock.json +25 -0
  28. agentcage-0.1.0/src/agentcage/data/patches/package.json +16 -0
  29. agentcage-0.1.0/src/agentcage/data/patches/proxy-fetch.mjs +19 -0
  30. agentcage-0.1.0/src/agentcage/data/proxy/addon.py +410 -0
  31. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/__init__.py +5 -0
  32. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/base.py +93 -0
  33. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/body_size.py +34 -0
  34. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/content_type.py +99 -0
  35. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/domain.py +46 -0
  36. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/entropy.py +147 -0
  37. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/secrets.py +117 -0
  38. agentcage-0.1.0/src/agentcage/data/proxy/inspectors/util.py +71 -0
  39. agentcage-0.1.0/src/agentcage/data/proxy/secret_injector.py +232 -0
  40. agentcage-0.1.0/src/agentcage/podman.py +122 -0
  41. agentcage-0.1.0/src/agentcage/py.typed +0 -0
  42. agentcage-0.1.0/src/agentcage/quadlets.py +124 -0
  43. agentcage-0.1.0/src/agentcage/state.py +99 -0
  44. agentcage-0.1.0/src/agentcage/systemd.py +21 -0
  45. agentcage-0.1.0/src/agentcage/templates/cage.container.j2 +88 -0
  46. agentcage-0.1.0/src/agentcage/templates/dns.container.j2 +17 -0
  47. agentcage-0.1.0/src/agentcage/templates/network.j2 +4 -0
  48. agentcage-0.1.0/src/agentcage/templates/proxy.container.j2 +30 -0
  49. agentcage-0.1.0/src/agentcage/templates/volume.j2 +2 -0
  50. agentcage-0.1.0/tests/__init__.py +0 -0
  51. agentcage-0.1.0/tests/agent/test-curl.sh +66 -0
  52. agentcage-0.1.0/tests/agent/test.js +88 -0
  53. agentcage-0.1.0/tests/cage/Containerfile +2 -0
  54. agentcage-0.1.0/tests/cage/config.yaml +20 -0
  55. agentcage-0.1.0/tests/cage/scripts/test-all.js +113 -0
  56. agentcage-0.1.0/tests/configs/test-curl.yaml +22 -0
  57. agentcage-0.1.0/tests/configs/test.yaml +22 -0
  58. agentcage-0.1.0/tests/conftest.py +107 -0
  59. agentcage-0.1.0/tests/test_addon.py +119 -0
  60. agentcage-0.1.0/tests/test_cage_cli.py +183 -0
  61. agentcage-0.1.0/tests/test_config.py +292 -0
  62. agentcage-0.1.0/tests/test_defaults.py +198 -0
  63. agentcage-0.1.0/tests/test_domain_cli.py +140 -0
  64. agentcage-0.1.0/tests/test_inspectors.py +730 -0
  65. agentcage-0.1.0/tests/test_quadlets.py +408 -0
  66. agentcage-0.1.0/tests/test_secret_cli.py +123 -0
  67. agentcage-0.1.0/tests/test_secret_injector.py +404 -0
  68. agentcage-0.1.0/uv.lock +222 -0
@@ -0,0 +1,18 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ - run: uv build
18
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,21 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.12", "3.13", "3.14"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - run: uv sync --dev
21
+ - run: uv run pytest
@@ -0,0 +1,11 @@
1
+ *.pyc
2
+ __pycache__/
3
+ .mitmproxy/
4
+ *.pem
5
+ .pytest_cache/
6
+ node_modules/
7
+ .venv/
8
+ .env
9
+ dist/
10
+ build/
11
+ *.egg-info/
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-02-17
9
+
10
+ ### Added
11
+
12
+ - CLI with `cage create`, `cage update`, `cage destroy`, `cage list`, `cage verify`, `cage reload`, and `cage logs` commands
13
+ - Secret management with `secret set`, `secret list`, and `secret rm` commands
14
+ - Domain management with `domain add`, `domain list`, and `domain rm` commands
15
+ - Network isolation via rootless Podman with `--internal` network (no internet gateway for the agent)
16
+ - Domain allowlist/blocklist filtering at both proxy and DNS layers
17
+ - Secret injection — the cage never sees real API keys; the proxy swaps placeholders transparently
18
+ - 19 built-in secret detection patterns (OpenAI, Anthropic, AWS, GitHub, Google, Slack, Stripe, and more)
19
+ - Built-in `allow_to_domains` mappings so standard API keys reach their provider domains without configuration
20
+ - Shannon entropy analysis for detecting encrypted/compressed exfiltration payloads
21
+ - Content-type mismatch and base64 blob detection
22
+ - Per-host token-bucket rate limiting
23
+ - WebSocket frame inspection (secrets, entropy)
24
+ - Custom inspector support via Python files
25
+ - Structured JSON audit logging
26
+ - Container hardening defaults (read-only root, dropped capabilities, no-new-privileges)
27
+ - Node.js `fetch()` proxy patch via `--import` loader
28
+ - Supply chain hardening (pinned image digests, lockfile integrity, patch file SHA-256 verification)
29
+ - systemd quadlet generation with proper dependency ordering
30
+ - OpenClaw example configuration and setup guide
31
+
32
+ [0.1.0]: https://github.com/agentcage/agentcage/releases/tag/v0.1.0
@@ -0,0 +1,31 @@
1
+ # Contributing to agentcage
2
+
3
+ ## Development Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/agentcage/agentcage.git
7
+ cd agentcage
8
+ uv sync --dev
9
+ ```
10
+
11
+ ## Running Tests
12
+
13
+ ```bash
14
+ uv run pytest
15
+ ```
16
+
17
+ ## Making Changes
18
+
19
+ 1. Fork the repository and create a feature branch.
20
+ 2. Make your changes and add tests where appropriate.
21
+ 3. Run `uv run pytest` and ensure all tests pass.
22
+ 4. Submit a pull request with a clear description of what changed and why.
23
+
24
+ ## Code Style
25
+
26
+ - Follow existing patterns in the codebase.
27
+ - Keep changes focused — one concern per PR.
28
+
29
+ ## Security Issues
30
+
31
+ Please **do not** open public issues for security vulnerabilities. See [SECURITY.md](SECURITY.md) for responsible disclosure instructions.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Luca Martinetti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,399 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentcage
3
+ Version: 0.1.0
4
+ Summary: Defense-in-depth proxy sandbox for AI agents
5
+ Project-URL: Homepage, https://github.com/agentcage/agentcage
6
+ Project-URL: Repository, https://github.com/agentcage/agentcage
7
+ Project-URL: Documentation, https://github.com/agentcage/agentcage/tree/master/docs
8
+ Project-URL: Issues, https://github.com/agentcage/agentcage/issues
9
+ Author: Luca Martinetti
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,ai,container,mitmproxy,proxy,sandbox,security
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Security
23
+ Classifier: Topic :: System :: Networking :: Monitoring
24
+ Requires-Python: >=3.12
25
+ Requires-Dist: click>=8.1
26
+ Requires-Dist: jinja2>=3.1
27
+ Requires-Dist: pyyaml>=6.0
28
+ Description-Content-Type: text/markdown
29
+
30
+ <p align="center">
31
+ <img src="docs/agentcage.png" alt="agentcage logo" width="250">
32
+ </p>
33
+
34
+ # agentcage
35
+
36
+ *Defense-in-depth proxy sandbox for AI agents.*
37
+
38
+ Sandboxed container environments for AI agents, powered by rootless [Podman](https://podman.io/) and [mitmproxy](https://mitmproxy.org/).
39
+
40
+ > ⚠️ **Warning:** This is an experimental project. It has not been audited by security professionals. Use it at your own risk. See [Security & Threat Model](docs/security.md) for details and known limitations.
41
+
42
+ > **Setting up OpenClaw?** See the [OpenClaw guide](docs/openclaw.md) and [`openclaw/config.yaml`](examples/openclaw/).
43
+
44
+ ## What is it?
45
+
46
+ agentcage is a CLI that generates hardened, sandboxed container environments for AI agents. It produces [systemd quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html) files that deploy three containers on a rootless [Podman](https://podman.io/) network -- no root privileges required. Your agent runs on an internal-only network with no internet gateway; the only way out is through an inspecting [mitmproxy](https://mitmproxy.org/) that scans every HTTP request before forwarding it.
47
+
48
+ ## Why is it needed?
49
+
50
+ Most AI agent deployments hand the agent a [**lethal trifecta**](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/):
51
+
52
+ 1. **Internet access** -- the agent can reach any server on the internet.
53
+ 2. **Credentials** -- API keys, tokens, and secrets are passed as environment variables or mounted files.
54
+ 3. **Arbitrary code execution** -- the agent runs code it writes itself, or code suggested by a model.
55
+
56
+ Any one of these alone is manageable. Combined, they create an exfiltration risk: if the agent is compromised, misaligned, or simply makes a mistake, it can send your credentials, source code, or private data to any endpoint on the internet. Most current setups have zero defense against this -- the agent has the same network access as any other process on the machine.
57
+
58
+ agentcage breaks the trifecta by placing the agent behind a defense-in-depth proxy sandbox: network isolation, domain filtering, secret injection, credential scanning, payload analysis, and container hardening -- all fail-closed. See [Security & Threat Model](docs/security.md) for the full breakdown of each layer and known limitations.
59
+
60
+ ## How does it work?
61
+
62
+ The agent container has no internet gateway. All HTTP traffic is routed via `HTTP_PROXY` / `HTTPS_PROXY` to a dual-homed mitmproxy container, which is the agent's only path to the outside world. A pluggable inspector chain evaluates every request -- enforcing domain allowlists, scanning for secret leaks, and optionally analyzing payloads -- before forwarding or blocking with a 403.
63
+
64
+ See [Architecture](docs/architecture.md) for the full container topology, inspector chain, startup order, and certificate sharing.
65
+
66
+ ## Prerequisites
67
+
68
+ - [Podman](https://podman.io/) (rootless)
69
+ - Python 3.12+
70
+ - [uv](https://docs.astral.sh/uv/) (Python package manager)
71
+
72
+ ### Linux
73
+
74
+ **Arch Linux:**
75
+
76
+ ```bash
77
+ sudo pacman -S podman python uv
78
+ ```
79
+
80
+ **Debian / Ubuntu (24.04+):**
81
+
82
+ ```bash
83
+ sudo apt install podman python3
84
+ curl -LsSf https://astral.sh/uv/install.sh | sh
85
+ ```
86
+
87
+ **Fedora:**
88
+
89
+ ```bash
90
+ sudo dnf install podman python3 uv
91
+ ```
92
+
93
+ ### macOS
94
+
95
+ ```bash
96
+ brew install podman python uv
97
+ podman machine init
98
+ podman machine start
99
+ ```
100
+
101
+ > **Note:** On macOS, Podman runs containers inside a Linux VM. `podman machine init` creates and `podman machine start` starts it.
102
+
103
+ ## Install
104
+
105
+ ```bash
106
+ uv tool install agentcage # from PyPI (when published)
107
+ uv tool install git+https://github.com/agentcage/agentcage.git # from GitHub
108
+ ```
109
+
110
+ Or for development:
111
+
112
+ ```bash
113
+ git clone https://github.com/agentcage/agentcage.git
114
+ cd agentcage
115
+ uv run agentcage --help
116
+ ```
117
+
118
+ ## Quick Start
119
+
120
+ ```bash
121
+ # Edit config (set your allowed domains, image, etc.)
122
+ cp examples/basic/config.yaml config.yaml
123
+
124
+ # Store secrets first (they're required before cage creation)
125
+ agentcage secret set myapp ANTHROPIC_API_KEY
126
+
127
+ # Create the cage (builds images, generates quadlets, starts containers)
128
+ agentcage cage create -c config.yaml
129
+
130
+ # Verify everything is healthy
131
+ agentcage cage verify myapp
132
+ ```
133
+
134
+ ## CLI Reference
135
+
136
+ The CLI is organized into two command groups: **`cage`** (manage cages) and **`secret`** (manage cage-scoped secrets).
137
+
138
+ ```
139
+ agentcage <group> <command> [options]
140
+ ```
141
+
142
+ ### `cage` -- Manage cages
143
+
144
+ | Command | Description |
145
+ |---|---|
146
+ | `cage create -c CONFIG` | Build images, generate quadlets, install, and start a new cage |
147
+ | `cage update NAME [-c CONFIG]` | Rebuild images and restart an existing cage |
148
+ | `cage list` | List all cages with status |
149
+ | `cage destroy NAME [-y]` | Stop containers, remove quadlets, state, and scoped secrets |
150
+ | `cage verify NAME` | Health checks (containers, certs, proxy, egress, rootless) |
151
+ | `cage reload NAME` | Restart containers without rebuilding images |
152
+
153
+ ### `secret` -- Manage cage-scoped secrets
154
+
155
+ | Command | Description |
156
+ |---|---|
157
+ | `secret list NAME` | List secrets for a cage (with status if cage exists) |
158
+ | `secret set NAME KEY` | Set a secret (prompts for value or reads stdin) |
159
+ | `secret rm NAME KEY` | Remove a secret |
160
+
161
+ ---
162
+
163
+ ### `cage create`
164
+
165
+ ```
166
+ agentcage cage create -c <config>
167
+ ```
168
+
169
+ Creates a new cage from a config file. This single command:
170
+
171
+ 1. Validates the config
172
+ 2. Checks that all required secrets exist in Podman
173
+ 3. Saves deployment state to `~/.config/agentcage/deployments/<name>/config.yaml`
174
+ 4. Builds the proxy and DNS container images
175
+ 5. Generates and installs 5 quadlet files into `~/.config/containers/systemd/`
176
+ 6. Reloads systemd and starts the cage
177
+
178
+ The generated quadlet files are:
179
+
180
+ - `<name>-net.network` -- internal network with fixed subnet
181
+ - `<name>-certs.volume` -- shared certificate volume
182
+ - `<name>-dns.container` -- DNS sidecar (dnsmasq)
183
+ - `<name>-proxy.container` -- mitmproxy with inspector chain
184
+ - `<name>-cage.container` -- your agent container
185
+
186
+ Fails if any required secrets are missing. The error message tells you exactly which secrets to create:
187
+
188
+ ```
189
+ error: missing secrets for cage 'myapp':
190
+ ANTHROPIC_API_KEY
191
+ Create them with:
192
+ agentcage secret set myapp ANTHROPIC_API_KEY
193
+ ```
194
+
195
+ ### `cage update`
196
+
197
+ ```
198
+ agentcage cage update <name> [-c <config>]
199
+ ```
200
+
201
+ Rebuild and restart an existing cage. Use this after changing code or config:
202
+
203
+ - **With `-c`**: Updates the stored config, then rebuilds and restarts.
204
+ - **Without `-c`**: Rebuilds from the previously stored config (useful when only the container image or proxy code has changed).
205
+
206
+ Stops the running services before rebuilding, then starts them again.
207
+
208
+ ### `cage list`
209
+
210
+ ```
211
+ agentcage cage list
212
+ ```
213
+
214
+ Lists all known cages with their current status:
215
+
216
+ ```
217
+ NAME STATUS
218
+ myapp running (3/3)
219
+ testcage stopped (0/3)
220
+ broken degraded (2/3)
221
+ ```
222
+
223
+ ### `cage destroy`
224
+
225
+ ```
226
+ agentcage cage destroy <name> [-y|--yes]
227
+ ```
228
+
229
+ Tears down a cage completely:
230
+
231
+ 1. Stops all containers (cage, proxy, DNS)
232
+ 2. Removes quadlet files from `~/.config/containers/systemd/`
233
+ 3. Removes the Podman network and certificate volume
234
+ 4. Removes all scoped secrets (e.g., `myapp.ANTHROPIC_API_KEY`)
235
+ 5. Removes deployment state from `~/.config/agentcage/deployments/<name>/`
236
+
237
+ User-defined named volumes and bind-mounted data are never removed. Pass `-y` to skip the confirmation prompt.
238
+
239
+ ### `cage verify`
240
+
241
+ ```
242
+ agentcage cage verify <name>
243
+ ```
244
+
245
+ Runs health checks against a running cage:
246
+
247
+ - All 3 containers running (cage, proxy, DNS)
248
+ - CA certificate present in the shared volume
249
+ - `HTTP_PROXY` / `HTTPS_PROXY` set in the cage container
250
+ - Egress filtering working (blocked domain returns 403)
251
+ - Podman running rootless
252
+
253
+ Example output:
254
+
255
+ ```
256
+ === agentcage verify: myapp ===
257
+
258
+ -- Containers --
259
+ [PASS] myapp-proxy is running
260
+ [PASS] myapp-dns is running
261
+ [PASS] myapp-cage is running
262
+
263
+ -- CA Certificate --
264
+ [PASS] mitmproxy CA cert exists in shared volume
265
+
266
+ -- Proxy Configuration --
267
+ [PASS] HTTP_PROXY is set
268
+ [PASS] HTTPS_PROXY is set
269
+
270
+ -- Egress Filtering --
271
+ [PASS] Blocked domain (evil-exfil-server.io) is denied (HTTP 403)
272
+
273
+ -- Podman --
274
+ [PASS] Podman is running rootless
275
+
276
+ === Results: 8 passed, 0 failed, 0 warnings ===
277
+ ```
278
+
279
+ ### `cage reload`
280
+
281
+ ```
282
+ agentcage cage reload <name>
283
+ ```
284
+
285
+ Restarts containers without rebuilding images. Useful after config-only changes (the config YAML is bind-mounted into the proxy container, so a restart picks it up).
286
+
287
+ ### `secret set`
288
+
289
+ ```
290
+ agentcage secret set <name> <key>
291
+ ```
292
+
293
+ Sets a deployment-scoped secret. When run interactively, prompts for the value with hidden input. Also accepts piped input:
294
+
295
+ ```bash
296
+ # Interactive (prompts for value)
297
+ agentcage secret set myapp ANTHROPIC_API_KEY
298
+
299
+ # Piped from a command
300
+ echo "sk-ant-abc123" | agentcage secret set myapp ANTHROPIC_API_KEY
301
+
302
+ # From a file
303
+ agentcage secret set myapp ANTHROPIC_API_KEY < /path/to/key.txt
304
+ ```
305
+
306
+ Secrets are stored in Podman as `<name>.<key>` (e.g., `myapp.ANTHROPIC_API_KEY`) and mapped back to the original env var name via `target=` in the quadlet templates, so the container sees `ANTHROPIC_API_KEY` as expected.
307
+
308
+ If the cage is currently running, it is automatically reloaded after the secret is set.
309
+
310
+ ### `secret list`
311
+
312
+ ```
313
+ agentcage secret list <name>
314
+ ```
315
+
316
+ Lists secrets for a cage. If the cage has deployment state, cross-references with the config to show expected secrets and their status:
317
+
318
+ ```
319
+ NAME TYPE STATUS
320
+ ANTHROPIC_API_KEY injection ok
321
+ GITHUB_TOKEN direct MISSING
322
+ ```
323
+
324
+ Secret types:
325
+ - **injection** -- managed by the proxy's secret injection system (the cage sees a placeholder; the proxy swaps in the real value)
326
+ - **direct** -- passed directly to the cage container via `podman_secrets`
327
+
328
+ If no deployment state exists, lists all Podman secrets matching the `<name>.` prefix.
329
+
330
+ ### `secret rm`
331
+
332
+ ```
333
+ agentcage secret rm <name> <key>
334
+ ```
335
+
336
+ Removes a secret from Podman. If the cage is currently running, it is automatically reloaded.
337
+
338
+ ---
339
+
340
+ ## Typical Workflow
341
+
342
+ ```bash
343
+ # 1. Write your config
344
+ cp examples/basic/config.yaml config.yaml
345
+ vim config.yaml
346
+
347
+ # 2. Store secrets (before creating the cage)
348
+ agentcage secret set myapp ANTHROPIC_API_KEY
349
+ agentcage secret set myapp GITHUB_TOKEN
350
+
351
+ # 3. Create the cage
352
+ agentcage cage create -c config.yaml
353
+
354
+ # 4. Verify it's healthy
355
+ agentcage cage verify myapp
356
+
357
+ # 5. View logs
358
+ journalctl --user -u myapp-cage -f
359
+
360
+ # 6. Update after code/config changes
361
+ agentcage cage update myapp -c config.yaml
362
+
363
+ # 7. Rotate a secret (auto-reloads the cage)
364
+ agentcage secret set myapp ANTHROPIC_API_KEY
365
+
366
+ # 8. Restart without rebuild (config-only change)
367
+ agentcage cage reload myapp
368
+
369
+ # 9. Tear it all down
370
+ agentcage cage destroy myapp
371
+ ```
372
+
373
+ ### View logs
374
+
375
+ ```bash
376
+ journalctl --user -u myapp-cage -f
377
+ journalctl --user -u myapp-proxy -f
378
+ journalctl --user -u myapp-dns -f
379
+ ```
380
+
381
+ ## Deployment State
382
+
383
+ agentcage tracks each cage in `~/.config/agentcage/deployments/<name>/config.yaml`. This stored config copy allows commands like `cage update` (without `-c`) and `cage reload` to operate without requiring the original config file. The state is removed when a cage is destroyed.
384
+
385
+ ## Architecture
386
+
387
+ Three containers on an internal Podman network: the agent (no internet gateway), a dual-homed DNS sidecar, and a dual-homed mitmproxy that inspects and forwards all traffic. See [Architecture](docs/architecture.md) for the full topology, inspector chain, startup order, and certificate sharing.
388
+
389
+ ## Configuration
390
+
391
+ See the [Configuration Reference](docs/configuration.md) for all settings, defaults, and examples. Example configs: [`basic/config.yaml`](examples/basic/) | [`openclaw/config.yaml`](examples/openclaw/)
392
+
393
+ ## Security
394
+
395
+ The agent has no internet gateway -- all traffic must pass through the proxy, which applies domain filtering, secret detection, payload inspection, and custom inspectors. See [Security & Threat Model](docs/security.md) for the full threat model, defense layers, and known limitations.
396
+
397
+ ## License
398
+
399
+ MIT