create-ironclaws 1.0.3 → 1.1.0
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.
- package/package.json +1 -1
- package/template/CLAUDE.md +105 -51
- package/template/container/Dockerfile.argus +14 -12
- package/template/container/skills/slack-formatting/SKILL.md +46 -47
- package/template/container/tools/README.md +33 -0
- package/template/docs/how-it-works.md +19 -19
- package/template/groups/forge/CLAUDE.md +13 -9
- package/template/scripts/setup-onecli-secrets.sh +25 -87
- package/template/src/container-runner.ts +4 -4
- package/template/src/index.ts +26 -5
- package/template/container/tools/elastic_query.py +0 -161
- package/template/container/tools/gdrive_tool.py +0 -185
- package/template/container/tools/jira_tool.py +0 -433
- package/template/container/tools/slack_history_tool.py +0 -144
- package/template/container/tools/youtube_tool.py +0 -174
- package/template/scripts/register-expense-agent.sh +0 -121
- package/template/setup-agents.sh +0 -142
package/package.json
CHANGED
package/template/CLAUDE.md
CHANGED
|
@@ -1,66 +1,123 @@
|
|
|
1
|
-
#
|
|
1
|
+
# IronClaws — AI Agent Platform
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This is an IronClaws deployment. It runs a fleet of AI agents over Slack.
|
|
4
4
|
|
|
5
5
|
## Architecture
|
|
6
6
|
|
|
7
|
-
Single Node.js host process. Each
|
|
7
|
+
Single Node.js host process. Each agent gets its own Docker container — isolated filesystem, memory, and credentials. The host handles Slack routing, scheduling, and security. Agents do the actual work.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Slack
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
IronClaws host (src/index.ts)
|
|
14
|
+
│ reads .env, agents.yaml, agent-credentials.yaml
|
|
15
|
+
│
|
|
16
|
+
├── Message router ──► spawns Docker container per agent
|
|
17
|
+
├── Task scheduler ──► spawns containers on schedule
|
|
18
|
+
└── IPC watcher ──► reads results from containers
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
Docker container (argus-claude:latest)
|
|
22
|
+
├── Claude Code (the AI)
|
|
23
|
+
├── agent-runner (IPC bridge)
|
|
24
|
+
├── Python tools (container/tools/)
|
|
25
|
+
└── Skills (container/skills/)
|
|
26
|
+
```
|
|
8
27
|
|
|
9
28
|
## Key Files
|
|
10
29
|
|
|
11
30
|
| File | Purpose |
|
|
12
31
|
|------|---------|
|
|
13
32
|
| `src/index.ts` | Main loop: message routing, agent invocation, state |
|
|
14
|
-
| `src/channels/slack.ts` | Slack
|
|
33
|
+
| `src/channels/slack.ts` | Slack Socket Mode integration |
|
|
15
34
|
| `src/container-runner.ts` | Spawns containers with correct mounts and env vars |
|
|
16
35
|
| `src/ipc.ts` | IPC file watcher — agents write here to send messages / schedule tasks |
|
|
17
36
|
| `src/task-scheduler.ts` | Cron-based task scheduling |
|
|
18
37
|
| `src/db.ts` | SQLite: messages, groups, sessions, tasks |
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
38
|
+
| `agents.yaml` | Declarative agent registry — single source of truth for the fleet |
|
|
39
|
+
| `agent-credentials.yaml` | Per-agent access control: which env vars, tools, and skills each agent gets |
|
|
21
40
|
| `groups/{name}/CLAUDE.md` | Per-agent identity and instructions |
|
|
22
|
-
| `container/Dockerfile.argus` | Agent container image
|
|
41
|
+
| `container/Dockerfile.argus` | Agent container image |
|
|
23
42
|
| `container/tools/` | Python tools available inside containers |
|
|
24
|
-
| `container/skills/` | Shared skills available to
|
|
43
|
+
| `container/skills/` | Shared skills (SKILL.md files) available to agents |
|
|
25
44
|
|
|
26
|
-
## Agent Fleet
|
|
45
|
+
## Your Agent Fleet
|
|
27
46
|
|
|
28
47
|
| Agent | Folder | Channel | Purpose |
|
|
29
48
|
|-------|--------|---------|---------|
|
|
30
|
-
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
49
|
+
| Forge | `forge` | Your channel | Built-in guide — helps you add new agents and troubleshoot |
|
|
50
|
+
|
|
51
|
+
Add more agents by creating a `groups/{name}/CLAUDE.md`, adding an entry to `agents.yaml`, and setting the channel ID in `.env`.
|
|
52
|
+
|
|
53
|
+
## Adding an Agent
|
|
54
|
+
|
|
55
|
+
**1. Create the agent instructions:**
|
|
56
|
+
```bash
|
|
57
|
+
mkdir -p groups/my-agent
|
|
58
|
+
# Write groups/my-agent/CLAUDE.md — the agent's identity, what it does, how to respond
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**2. Register in `agents.yaml`:**
|
|
62
|
+
```yaml
|
|
63
|
+
- folder: my-agent
|
|
64
|
+
name: "My Agent"
|
|
65
|
+
trigger: "@Argus"
|
|
66
|
+
channel_env: MY_AGENT_CHANNEL_ID
|
|
67
|
+
requires_trigger: false
|
|
68
|
+
onecli_secrets: [litellm]
|
|
69
|
+
onecli_id: <python3 -c "import uuid; print(uuid.uuid4())">
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**3. Set the channel ID in `.env`:**
|
|
73
|
+
```
|
|
74
|
+
MY_AGENT_CHANNEL_ID=C...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**4. Restart IronClaws** — agents auto-register on startup. No script needed.
|
|
37
78
|
|
|
38
79
|
## Container Image
|
|
39
80
|
|
|
40
|
-
All agents
|
|
81
|
+
All agents share one image: `argus-claude:latest`. Build it with:
|
|
41
82
|
```bash
|
|
42
|
-
cd container && ./build-argus.sh
|
|
83
|
+
cd container && ./build.sh && ./build-argus.sh
|
|
43
84
|
```
|
|
44
85
|
|
|
45
|
-
|
|
86
|
+
## Tools
|
|
87
|
+
|
|
88
|
+
Located in `container/tools/` — baked into the image at build time. There are no default tools. You add the tools your agents need.
|
|
46
89
|
|
|
47
|
-
|
|
90
|
+
Drop a Python script into `container/tools/`, rebuild the image, then grant access in `agent-credentials.yaml`:
|
|
91
|
+
```yaml
|
|
92
|
+
agents:
|
|
93
|
+
my-agent:
|
|
94
|
+
tools: [my_tool.py]
|
|
95
|
+
config: [MY_SERVICE_URL]
|
|
96
|
+
```
|
|
48
97
|
|
|
49
|
-
|
|
50
|
-
- `elastic_query.py` — Kibana/Elastic log querying
|
|
51
|
-
- `jira_tool.py` — Jira CRUD (get, search, create, update, comment, assign)
|
|
52
|
-
- `gdrive_tool.py` — Google Drive transcript reading
|
|
53
|
-
- `slack_history_tool.py` — Slack channel history fetching
|
|
98
|
+
See `container/tools/README.md` for design principles and auth patterns.
|
|
54
99
|
|
|
55
100
|
## Skills Available Inside Containers
|
|
56
101
|
|
|
57
|
-
Located in `container/skills/` —
|
|
58
|
-
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
102
|
+
Located in `container/skills/` — mounted at runtime, no rebuild needed.
|
|
103
|
+
|
|
104
|
+
- `slack-formatting` — Slack mrkdwn formatting rules (loaded by all agents)
|
|
105
|
+
- `capabilities` — lets agents list available tools
|
|
61
106
|
- `status` — system health check
|
|
62
|
-
- `agent-
|
|
63
|
-
- `
|
|
107
|
+
- `agent-browser` — web browsing capability
|
|
108
|
+
- `agent-status` — dashboard of all running agents
|
|
109
|
+
- `edit-agent` — collaborative CLAUDE.md editing from Slack
|
|
110
|
+
|
|
111
|
+
## Credentials and Security
|
|
112
|
+
|
|
113
|
+
The `agent-credentials.yaml` file controls what each agent can access:
|
|
114
|
+
- `config:` — env vars from `.env` forwarded to the container
|
|
115
|
+
- `tools:` — Python scripts mounted at `/workspace/extra/tools/`
|
|
116
|
+
- `skills:` — SKILL.md files made available
|
|
117
|
+
|
|
118
|
+
Dangerous skills (`edit-agent`, `agent-browser`, `agent-status`) are not in the default set — agents must explicitly opt in. See `agent-credentials.yaml`.
|
|
119
|
+
|
|
120
|
+
Service API credentials (Jira, Slack, etc.) are never in containers. The OneCLI proxy intercepts HTTPS traffic and injects `Authorization` headers server-side. See `docs/how-it-works.md` → Secrets Management.
|
|
64
121
|
|
|
65
122
|
## Runtime Config
|
|
66
123
|
|
|
@@ -68,37 +125,34 @@ Key env vars (set in `.env`):
|
|
|
68
125
|
```
|
|
69
126
|
SLACK_BOT_TOKEN Slack bot token (xoxb-...)
|
|
70
127
|
SLACK_APP_TOKEN Slack app-level token (xapp-...)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
ELASTIC_BASE_URL Kibana base URL
|
|
74
|
-
ELASTIC_API_KEY Kibana API key
|
|
75
|
-
JIRA_BASE_URL https://ardoqcom.atlassian.net
|
|
76
|
-
JIRA_EMAIL Jira account email
|
|
77
|
-
JIRA_API_TOKEN Jira API token
|
|
78
|
-
JIRA_PROJECT_KEY IAI
|
|
128
|
+
ANTHROPIC_BASE_URL LiteLLM gateway URL
|
|
129
|
+
ANTHROPIC_AUTH_TOKEN LiteLLM auth token
|
|
79
130
|
CONTAINER_IMAGE argus-claude:latest
|
|
80
131
|
```
|
|
81
132
|
|
|
133
|
+
See `.env.example` for the full list with descriptions.
|
|
134
|
+
|
|
82
135
|
## Security
|
|
83
136
|
|
|
84
|
-
- Mount allowlist: `~/.config/nanoclaw/mount-allowlist.json` — controls what host paths containers can access
|
|
85
|
-
- Sender allowlist: `~/.config/nanoclaw/sender-allowlist.json` — per-channel sender filtering
|
|
86
|
-
-
|
|
87
|
-
- `github-app.pem` is gitignored — never commit
|
|
137
|
+
- Mount allowlist: `~/.config/nanoclaw/mount-allowlist.json` — controls what host paths containers can access. Outside the project directory so containers can't read or modify it.
|
|
138
|
+
- Sender allowlist: `~/.config/nanoclaw/sender-allowlist.json` — per-channel sender filtering. Also outside the project directory.
|
|
139
|
+
- `*.pem` files are gitignored — never commit private keys
|
|
88
140
|
|
|
89
141
|
## Running
|
|
90
142
|
|
|
91
143
|
```bash
|
|
92
|
-
|
|
93
|
-
npm run
|
|
94
|
-
npm start
|
|
144
|
+
docker compose up -d # Start OneCLI credential proxy
|
|
145
|
+
npm run dev # Start IronClaws (development, hot reload)
|
|
146
|
+
npm run build && npm start # Production
|
|
95
147
|
```
|
|
96
148
|
|
|
97
149
|
## First-Time Setup
|
|
98
150
|
|
|
99
151
|
1. Copy `.env.example` to `.env` and fill in all values
|
|
100
|
-
2.
|
|
101
|
-
3.
|
|
102
|
-
4.
|
|
103
|
-
5.
|
|
104
|
-
6.
|
|
152
|
+
2. Start OneCLI: `docker compose up -d`
|
|
153
|
+
3. Build the container image: `cd container && ./build.sh && ./build-argus.sh`
|
|
154
|
+
4. Start IronClaws: `npm run dev`
|
|
155
|
+
5. Agents auto-register on startup — no script needed
|
|
156
|
+
6. Say hello in the configured Slack channel
|
|
157
|
+
|
|
158
|
+
For credential registration (Jira, Elastic, etc.): `bash scripts/setup-onecli-secrets.sh`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Extends the NanoClaw
|
|
3
|
-
#
|
|
1
|
+
# IronClaws Agent Container
|
|
2
|
+
# Extends the base NanoClaw image with Python and the gh CLI.
|
|
3
|
+
# This is intentionally minimal — add your own dependencies as needed.
|
|
4
4
|
#
|
|
5
5
|
# Build the base image first: ./container/build.sh
|
|
6
6
|
# Then build this image: ./container/build-argus.sh
|
|
@@ -9,24 +9,26 @@ FROM nanoclaw-agent:latest
|
|
|
9
9
|
|
|
10
10
|
USER root
|
|
11
11
|
|
|
12
|
-
# Python 3 + pip
|
|
12
|
+
# Python 3 + pip — required to run tools from container/tools/
|
|
13
|
+
# requests: foundational HTTP library; most tools will need it
|
|
13
14
|
RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
|
|
14
|
-
RUN pip3 install requests
|
|
15
|
+
RUN pip3 install requests --break-system-packages
|
|
15
16
|
|
|
16
|
-
#
|
|
17
|
-
RUN pip3 install poetry --break-system-packages
|
|
18
|
-
|
|
19
|
-
# gh CLI
|
|
17
|
+
# gh CLI — for agents that work with GitHub (PR creation, issue management, etc.)
|
|
20
18
|
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
|
21
19
|
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null && \
|
|
22
20
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] \
|
|
23
21
|
https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
|
|
24
22
|
apt-get update && apt-get install -y gh && rm -rf /var/lib/apt/lists/*
|
|
25
23
|
|
|
26
|
-
#
|
|
27
|
-
|
|
24
|
+
# ── Add your own dependencies here ────────────────────────────────────────────
|
|
25
|
+
# Examples:
|
|
26
|
+
# RUN pip3 install tenacity pyjwt pyyaml --break-system-packages
|
|
27
|
+
# RUN pip3 install poetry --break-system-packages
|
|
28
|
+
# RUN npm install -g @moonrepo/cli
|
|
28
29
|
|
|
29
|
-
#
|
|
30
|
+
# Tools — baked into the image at build time
|
|
31
|
+
# Add Python scripts to container/tools/ and rebuild to make them available
|
|
30
32
|
COPY tools/ /workspace/extra/tools/
|
|
31
33
|
RUN chown -R node:node /workspace/extra/tools && chmod -R 755 /workspace/extra/tools
|
|
32
34
|
|
|
@@ -42,25 +42,25 @@ Tables don't render. Use these patterns instead:
|
|
|
42
42
|
|
|
43
43
|
**Field list (best for structured data):**
|
|
44
44
|
```
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
*Ticket:* PROJ-042
|
|
46
|
+
*Assignee:* eng@yourcompany.com
|
|
47
|
+
*Priority:* High
|
|
48
|
+
*Due:* 2026-06-30
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
**Compact inline (best for short summaries):**
|
|
52
52
|
```
|
|
53
|
-
|
|
53
|
+
PROJ-042 • Deploy pipeline fix • High • Due 2026-06-30
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
**Key-value in code block (best for exact copy-paste, e.g. email drafts):**
|
|
57
57
|
````
|
|
58
58
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
Ticket: PROJ-042
|
|
60
|
+
Summary: Deploy pipeline fix
|
|
61
|
+
Priority: High
|
|
62
|
+
Assignee: eng@yourcompany.com
|
|
63
|
+
Due date: 2026-06-30
|
|
64
64
|
```
|
|
65
65
|
````
|
|
66
66
|
|
|
@@ -94,13 +94,12 @@ _Footer — instructions or next steps_
|
|
|
94
94
|
```
|
|
95
95
|
:red_circle: *1 violation found — action required*
|
|
96
96
|
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*Issue:* Vendor invoice posted to 6784 — must be reclassified by Amesto
|
|
97
|
+
*Item:* PROJ-042
|
|
98
|
+
*Assigned to:* eng@yourcompany.com
|
|
99
|
+
*Found:* 2026-06-15
|
|
100
|
+
*Issue:* Missing required field — needs manual review before proceeding
|
|
102
101
|
|
|
103
|
-
>
|
|
102
|
+
> Team Lead — please review and confirm the correct value.
|
|
104
103
|
```
|
|
105
104
|
|
|
106
105
|
---
|
|
@@ -108,11 +107,11 @@ _Footer — instructions or next steps_
|
|
|
108
107
|
## Status summaries
|
|
109
108
|
|
|
110
109
|
```
|
|
111
|
-
:white_check_mark: *
|
|
110
|
+
:white_check_mark: *Check complete — June 2026*
|
|
112
111
|
|
|
113
|
-
•
|
|
114
|
-
• :red_circle:
|
|
115
|
-
•
|
|
112
|
+
• Items reviewed: 14 | Findings: 3
|
|
113
|
+
• :red_circle: 1 critical | :large_yellow_circle: 2 warnings
|
|
114
|
+
• :large_green_circle: 11 clean
|
|
116
115
|
```
|
|
117
116
|
|
|
118
117
|
---
|
|
@@ -122,25 +121,26 @@ _Footer — instructions or next steps_
|
|
|
122
121
|
Always use a triple-backtick code block. This makes it copy-paste ready and visually distinct:
|
|
123
122
|
|
|
124
123
|
````
|
|
125
|
-
Here's the
|
|
124
|
+
Here's the draft for your review:
|
|
126
125
|
|
|
127
126
|
```
|
|
128
|
-
To:
|
|
129
|
-
Cc:
|
|
130
|
-
Subject:
|
|
127
|
+
To: recipient@theircompany.com
|
|
128
|
+
Cc: team@yourcompany.com
|
|
129
|
+
Subject: Action required — PROJ-042
|
|
131
130
|
|
|
132
|
-
Hi [
|
|
131
|
+
Hi [Name],
|
|
133
132
|
|
|
134
|
-
Please
|
|
133
|
+
Please review the following item and confirm the correction below.
|
|
135
134
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
Item: PROJ-042
|
|
136
|
+
Details: [description]
|
|
137
|
+
Action: [what needs to happen]
|
|
138
|
+
Deadline: [date]
|
|
139
|
+
|
|
140
|
+
Please confirm once resolved.
|
|
141
141
|
|
|
142
142
|
Thanks,
|
|
143
|
-
|
|
143
|
+
[Your Name]
|
|
144
144
|
```
|
|
145
145
|
````
|
|
146
146
|
|
|
@@ -151,10 +151,10 @@ Christian Dotterweich
|
|
|
151
151
|
Use `send_message` for long-running tasks so people know you're working:
|
|
152
152
|
|
|
153
153
|
```
|
|
154
|
-
:hourglass_flowing_sand: Fetching
|
|
154
|
+
:hourglass_flowing_sand: Fetching data from the API...
|
|
155
155
|
```
|
|
156
156
|
```
|
|
157
|
-
:mag: Found 3
|
|
157
|
+
:mag: Found 3 items — running checks...
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
---
|
|
@@ -162,12 +162,11 @@ Use `send_message` for long-running tasks so people know you're working:
|
|
|
162
162
|
## Escalations and warnings
|
|
163
163
|
|
|
164
164
|
```
|
|
165
|
-
:rotating_light: *
|
|
165
|
+
:rotating_light: *Review required before proceeding*
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
This task cannot complete automatically. Human judgment needed.
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
`annual true-up done 2025: <summary including adjustment amount>`
|
|
169
|
+
Please reply with your decision or `skip` to defer.
|
|
171
170
|
```
|
|
172
171
|
|
|
173
172
|
---
|
|
@@ -175,13 +174,13 @@ Reply with:
|
|
|
175
174
|
## Confirmations and success
|
|
176
175
|
|
|
177
176
|
```
|
|
178
|
-
:white_check_mark: *Done* —
|
|
177
|
+
:white_check_mark: *Done* — state updated in flagged_items.json
|
|
179
178
|
```
|
|
180
179
|
|
|
181
180
|
```
|
|
182
|
-
:white_check_mark: *
|
|
181
|
+
:white_check_mark: *Check complete — PROJ — June 2026*
|
|
183
182
|
|
|
184
|
-
:red_circle: 1 violation | :large_green_circle:
|
|
183
|
+
:red_circle: 1 violation | :large_green_circle: 3 compliant
|
|
185
184
|
```
|
|
186
185
|
|
|
187
186
|
---
|
|
@@ -192,9 +191,9 @@ Use `•` for bullets. Never `1.` numbered lists (they don't render as lists in
|
|
|
192
191
|
|
|
193
192
|
```
|
|
194
193
|
What was checked:
|
|
195
|
-
•
|
|
196
|
-
• Period:
|
|
197
|
-
•
|
|
194
|
+
• Data source: API
|
|
195
|
+
• Period: 2026-06 (June)
|
|
196
|
+
• Items reviewed: 14
|
|
198
197
|
```
|
|
199
198
|
|
|
200
199
|
---
|
|
@@ -202,9 +201,9 @@ What was checked:
|
|
|
202
201
|
## Mentions and links
|
|
203
202
|
|
|
204
203
|
```
|
|
205
|
-
<@
|
|
206
|
-
<#
|
|
207
|
-
<https://
|
|
204
|
+
<@USERID> # Mention a specific user
|
|
205
|
+
<#CHANNELID|channel-name> # Link a channel
|
|
206
|
+
<https://app.yourservice.com/item/123|View> # Named link
|
|
208
207
|
```
|
|
209
208
|
|
|
210
209
|
---
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Tools
|
|
2
|
+
|
|
3
|
+
Add Python scripts here that your agents need. Each script becomes available
|
|
4
|
+
inside containers at `/workspace/extra/tools/<script-name>`.
|
|
5
|
+
|
|
6
|
+
## How to add a tool
|
|
7
|
+
|
|
8
|
+
1. Drop your Python script here: `container/tools/my_tool.py`
|
|
9
|
+
2. Rebuild the container image: `cd container && ./build-argus.sh`
|
|
10
|
+
3. Grant access to specific agents in `agent-credentials.yaml`:
|
|
11
|
+
```yaml
|
|
12
|
+
agents:
|
|
13
|
+
my-agent:
|
|
14
|
+
tools: [my_tool.py]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Design principles
|
|
18
|
+
|
|
19
|
+
- One purpose per tool. A Jira tool does Jira things. A database tool does database things.
|
|
20
|
+
- Output JSON to stdout. Errors to stderr. Exit non-zero on failure.
|
|
21
|
+
- Auth: don't put credentials in tools. Use the OneCLI proxy (`HTTPS_PROXY` is set
|
|
22
|
+
automatically in every container — outbound requests get Authorization headers
|
|
23
|
+
injected by the proxy for any service you've configured in OneCLI).
|
|
24
|
+
- If a service embeds credentials in request bodies (not headers), pass them via
|
|
25
|
+
env vars listed in `agent-credentials.yaml` → `config:`.
|
|
26
|
+
|
|
27
|
+
## What's available inside containers
|
|
28
|
+
|
|
29
|
+
- Python 3 with `requests` — for HTTP calls
|
|
30
|
+
- `gh` CLI — for GitHub operations (PR creation, issue management)
|
|
31
|
+
- All skills from `container/skills/`
|
|
32
|
+
|
|
33
|
+
Add dependencies to `container/Dockerfile.argus` and rebuild.
|
|
@@ -113,7 +113,7 @@ This is the most important system to understand. The design goal: **no long-live
|
|
|
113
113
|
|
|
114
114
|
### The Four Credential Categories
|
|
115
115
|
|
|
116
|
-
#### A. Service API Keys (
|
|
116
|
+
#### A. Service API Keys (Jira, Slack, Elastic, Confluence, and any other services you configure)
|
|
117
117
|
These never enter containers at all. The OneCLI proxy intercepts HTTPS requests and injects the `Authorization` header server-side. The container makes a request to `jira.atlassian.com`, OneCLI intercepts, adds `Authorization: Basic <token>`, forwards it. The container only ever sees the base URL.
|
|
118
118
|
|
|
119
119
|
```
|
|
@@ -136,10 +136,10 @@ Same pattern as GitHub. The host holds the OAuth refresh token. Before spawning,
|
|
|
136
136
|
|
|
137
137
|
**Where to read:** `src/google-token.ts`, `container-runner.ts:470–478`
|
|
138
138
|
|
|
139
|
-
#### D.
|
|
140
|
-
|
|
139
|
+
#### D. Services that embed credentials in request bodies (the exception)
|
|
140
|
+
Some APIs embed credentials in JSON request bodies rather than HTTP headers (e.g. certain payment or partner APIs). OneCLI can only inject headers — it cannot inject body parameters. For these, the credentials must be passed as env vars directly to the container. This is explicitly documented as a known trade-off, and only the agents that specifically need them should receive them (principle of least privilege).
|
|
141
141
|
|
|
142
|
-
**Where to read:** `agent-credentials.yaml`
|
|
142
|
+
**Where to read:** `agent-credentials.yaml` — add these under `config:` for the relevant agent
|
|
143
143
|
|
|
144
144
|
### Per-Agent Selective Credentials
|
|
145
145
|
|
|
@@ -148,7 +148,7 @@ Each agent only gets the credentials it actually needs. This is configured in tw
|
|
|
148
148
|
**`agent-credentials.yaml`** — controls which env vars from the host's `.env` are forwarded:
|
|
149
149
|
```yaml
|
|
150
150
|
agents:
|
|
151
|
-
|
|
151
|
+
my-agent:
|
|
152
152
|
config:
|
|
153
153
|
- GITHUB_TOKEN # gets a fresh token injected
|
|
154
154
|
- ELASTIC_BASE_URL # just a URL, not a secret
|
|
@@ -156,7 +156,7 @@ agents:
|
|
|
156
156
|
|
|
157
157
|
**`agents.yaml`** — controls which OneCLI credential sets are linked (for service auth via proxy):
|
|
158
158
|
```yaml
|
|
159
|
-
- folder:
|
|
159
|
+
- folder: my-agent
|
|
160
160
|
onecli_secrets: [slack, litellm] # can call Slack API + Claude API
|
|
161
161
|
```
|
|
162
162
|
|
|
@@ -187,7 +187,7 @@ When OneCLI intercepts a request:
|
|
|
187
187
|
3. If yes: injects the `Authorization: Bearer <secret>` header
|
|
188
188
|
4. If no credential: proxies the request unchanged (or blocks if configured to do so)
|
|
189
189
|
|
|
190
|
-
The `access_token` in the proxy URL is the per-agent token stored in OneCLI's PostgreSQL database. It's
|
|
190
|
+
The `access_token` in the proxy URL is the per-agent token stored in OneCLI's PostgreSQL database. It's generated when the agent is first registered (automatically on startup).
|
|
191
191
|
|
|
192
192
|
### Git Authentication Fix
|
|
193
193
|
|
|
@@ -201,7 +201,7 @@ GIT_CONFIG_VALUE_0=Authorization: Basic <base64(x:token)>
|
|
|
201
201
|
- `src/container-runner.ts:482–499` — where `applyContainerConfig()` is called
|
|
202
202
|
- `node_modules/@onecli-sh/sdk/lib/index.js` — what it actually injects
|
|
203
203
|
- `agents.yaml` — `onecli_id` and `onecli_secrets` per agent
|
|
204
|
-
- `
|
|
204
|
+
- `src/index.ts` — `autoRegisterAgentsFromYaml()` — how agents are registered on startup
|
|
205
205
|
|
|
206
206
|
---
|
|
207
207
|
|
|
@@ -227,12 +227,12 @@ The `REJECT` (not `DROP`) matters: with `DROP`, a blocked connection hangs for m
|
|
|
227
227
|
The iptables rules only allow port 10255 (OneCLI proxy). Since `HTTPS_PROXY` is set in the container, ALL HTTPS calls go through port 10255 automatically. So:
|
|
228
228
|
- Direct `api.anthropic.com:443` connections → REJECTED (but these go through proxy anyway)
|
|
229
229
|
- Claude API calls → port 10255 → OneCLI → forwarded with credentials → OK
|
|
230
|
-
-
|
|
230
|
+
- Calls to any service with no credential → port 10255 → OneCLI → forwarded unchanged → service decides auth
|
|
231
231
|
- Any unauthorized service → port 10255 → OneCLI → no credential → 401 or blocked
|
|
232
232
|
|
|
233
233
|
### Cleanup
|
|
234
234
|
|
|
235
|
-
Rules are tagged with the container name (`--comment "nanoclaw-
|
|
235
|
+
Rules are tagged with the container name (`--comment "nanoclaw-my-agent-123"`). When the container exits, all its rules are deleted. On startup, stale rules from any previous run are cleaned up automatically.
|
|
236
236
|
|
|
237
237
|
**Where to read:**
|
|
238
238
|
- `src/network-policy.ts` — `applyContainerIptables()`, `cleanupContainerIptables()`
|
|
@@ -255,7 +255,7 @@ Each group has its own IPC directory at `data/ipc/{agentFolder}/`. Agents can on
|
|
|
255
255
|
Each container only gets the skills and tools listed in `agent-credentials.yaml`. See [Section 7](#7-tools-and-skills).
|
|
256
256
|
|
|
257
257
|
### Worktrees
|
|
258
|
-
When an agent needs to modify code (e.g.
|
|
258
|
+
When an agent needs to modify code (e.g. an agent raising a PR), it doesn't work on your live checkout. NanoClaw creates a git worktree — a separate clone of the repo — at `data/worktrees/{agentFolder}/repo/`. This is mounted read-write into the container while the actual repo stays untouched.
|
|
259
259
|
|
|
260
260
|
**Where to read:**
|
|
261
261
|
- `src/worktree.ts` — worktree creation/management
|
|
@@ -279,15 +279,15 @@ common:
|
|
|
279
279
|
tools: [] # no tools by default
|
|
280
280
|
|
|
281
281
|
agents:
|
|
282
|
-
|
|
282
|
+
alert-agent:
|
|
283
283
|
skills: [] # adds nothing extra
|
|
284
|
-
tools: [
|
|
285
|
-
|
|
284
|
+
tools: [my_tool.py] # gets this tool
|
|
285
|
+
meta-agent:
|
|
286
286
|
skills: [agent-browser, agent-status, edit-agent] # dangerous skills
|
|
287
|
-
tools: [
|
|
287
|
+
tools: [my_tool.py, other_tool.py] # all tools
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
-
**Dangerous skills** (`edit-agent`, `agent-browser`, `agent-status`) are NOT in the common layer. Only `
|
|
290
|
+
**Dangerous skills** (`edit-agent`, `agent-browser`, `agent-status`) are NOT in the common layer. Only agents that explicitly list them in `agent-credentials.yaml` get them — typically just your main/meta agent.
|
|
291
291
|
|
|
292
292
|
### How It's Enforced
|
|
293
293
|
|
|
@@ -395,12 +395,12 @@ If `wakeAgent: false`, the task ends without calling Claude — useful for tasks
|
|
|
395
395
|
## 10. Agent Registration
|
|
396
396
|
|
|
397
397
|
### Automatic Registration on Startup
|
|
398
|
-
|
|
398
|
+
IronClaws reads `agents.yaml` on every startup and auto-registers any agent whose channel ID env var is set in `.env` but isn't in the DB yet. A fresh install only requires filling in `.env` and starting IronClaws — no manual script needed.
|
|
399
399
|
|
|
400
400
|
The `autoRegisterAgentsFromYaml()` function in `src/index.ts` handles this. It also runs `scripts/setup-onecli-secrets.sh` automatically when credentials change (detected via hash of relevant env vars).
|
|
401
401
|
|
|
402
402
|
### Dynamic Registration (Main Group)
|
|
403
|
-
The
|
|
403
|
+
The main agent (`is_main: true` in `agents.yaml`) can register new agents at runtime using the `register_group` MCP tool. Only the main group can do this — IronClaws enforces this at the IPC processing level.
|
|
404
404
|
|
|
405
405
|
### What Registration Does
|
|
406
406
|
|
|
@@ -492,5 +492,5 @@ If you want to go deeper on a specific area:
|
|
|
492
492
|
| Network security | `src/network-policy.ts` |
|
|
493
493
|
| How agents talk back | `src/ipc.ts` + `container/agent-runner/src/ipc-mcp-stdio.ts` |
|
|
494
494
|
| Scheduling | `src/task-scheduler.ts` |
|
|
495
|
-
| What OneCLI does | `
|
|
495
|
+
| What OneCLI does | `docker-compose.yml` + `node_modules/@onecli-sh/sdk/lib/index.js` |
|
|
496
496
|
| Security model end-to-end | This doc → `src/mount-security.ts` → `src/network-policy.ts` |
|
|
@@ -63,7 +63,7 @@ Tone, format, constraints.
|
|
|
63
63
|
```yaml
|
|
64
64
|
my-agent:
|
|
65
65
|
skills: []
|
|
66
|
-
tools: [
|
|
66
|
+
tools: [my_tool.py] # tools from container/tools/
|
|
67
67
|
config:
|
|
68
68
|
- SOME_API_URL
|
|
69
69
|
```
|
|
@@ -72,16 +72,20 @@ Tone, format, constraints.
|
|
|
72
72
|
|
|
73
73
|
Agents never see raw API keys. OneCLI (the HTTPS proxy) intercepts outbound requests and injects Authorization headers. `onecli_secrets` in `agents.yaml` controls which credentials flow to which agent. Run `bash scripts/setup-onecli-secrets.sh` to register new credentials — this runs automatically on startup when credentials change.
|
|
74
74
|
|
|
75
|
-
###
|
|
75
|
+
### Tools
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|------|-------------|
|
|
79
|
-
| `jira_tool.py` | Jira CRUD — get, search, create, update, comment |
|
|
80
|
-
| `elastic_query.py` | Query Kibana/Elasticsearch |
|
|
81
|
-
| `slack_history_tool.py` | Read Slack channel history |
|
|
82
|
-
| `gdrive_tool.py` | Read Google Drive files |
|
|
77
|
+
There are no default tools — tools are specific to each deployment. To add one:
|
|
83
78
|
|
|
84
|
-
|
|
79
|
+
1. Write a Python script and drop it in `container/tools/my_tool.py`
|
|
80
|
+
2. Rebuild the image: `cd container && ./build-argus.sh`
|
|
81
|
+
3. Grant it to the agent in `agent-credentials.yaml`:
|
|
82
|
+
```yaml
|
|
83
|
+
agents:
|
|
84
|
+
my-agent:
|
|
85
|
+
tools: [my_tool.py]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Tool design:** output JSON to stdout, errors to stderr, exit non-zero on failure. Auth goes through the OneCLI proxy — don't put credentials in tools. See `container/tools/README.md`.
|
|
85
89
|
|
|
86
90
|
---
|
|
87
91
|
|