@meffecta/agent 1.0.0 → 1.0.2
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/README.md +34 -4
- package/bin/meffecta-agent.js +26 -8
- package/engine.json +2 -2
- package/lib/commands.js +80 -21
- package/lib/doctor.js +452 -0
- package/lib/flags.js +82 -0
- package/lib/integrations.js +230 -0
- package/package.json +3 -3
- package/scripts/lib/read-json.mjs +68 -0
- package/scripts/setup-scheduler.sh +6 -33
- package/scripts/update-tooling.sh +6 -5
- package/scripts/verify-credentials.mjs +19 -0
- package/ARCHITECTURE.md +0 -197
- package/IMPLEMENTATION.md +0 -292
package/IMPLEMENTATION.md
DELETED
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
# Setting up a new agent
|
|
2
|
-
|
|
3
|
-
Every step from nothing to a first run, in order. For how the pieces fit and why, see
|
|
4
|
-
[ARCHITECTURE.md](ARCHITECTURE.md).
|
|
5
|
-
|
|
6
|
-
Everything here is one command-line tool, `npx @meffecta/agent`, run from **your content
|
|
7
|
-
repo** — the directory step 3 creates, which holds this deployment's jobs and its settings.
|
|
8
|
-
You never need the engine's source: the tool and the engine image it deploys are published
|
|
9
|
-
together, and installing the tool is all the access you need.
|
|
10
|
-
|
|
11
|
-
npx @meffecta/agent steps # this guide, condensed to the command for each step
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 1. Create a GCP project
|
|
16
|
-
|
|
17
|
-
Give the agent a project of its own, separate from any product project it will read: this
|
|
18
|
-
project's service account gets project-wide secret access, and the mail tokens stored here
|
|
19
|
-
must not be readable by another system's machinery.
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
gcloud auth login
|
|
23
|
-
npx @meffecta/agent create-project
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
It asks for a display name, suggests a project ID from it, validates the ID against
|
|
27
|
-
Google's rules before spending a round trip, and creates the project. Pass
|
|
28
|
-
`--name`/`--id` to skip the prompts, or `ORGANIZATION=…` / `FOLDER=…` to place it.
|
|
29
|
-
|
|
30
|
-
- [ ] Note the **project ID** it prints. Project IDs are globally unique, so a plain name
|
|
31
|
-
is often taken and you end up with a suffixed one (`acme-agent-506513`). The id, not
|
|
32
|
-
the display name, is what every later command needs.
|
|
33
|
-
|
|
34
|
-
## 2. Link a billing account
|
|
35
|
-
|
|
36
|
-
Nothing else works without this: provisioning starts by enabling APIs, which fails on an
|
|
37
|
-
unbilled project.
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npx @meffecta/agent link-billing --project <PROJECT_ID>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
It lists the billing accounts you can use, marks closed ones as unselectable (linking one
|
|
44
|
-
appears to succeed and leaves the project unbilled), links your choice, and then confirms
|
|
45
|
-
the project really is billed rather than trusting the command's exit code.
|
|
46
|
-
|
|
47
|
-
- [ ] `billingEnabled: true`
|
|
48
|
-
|
|
49
|
-
If it reports a **billing quota**, that is the account's cap on how many projects it may
|
|
50
|
-
fund, not a problem with this project — free a slot with `gcloud billing projects unlink
|
|
51
|
-
<PROJECT>`, or request an increase.
|
|
52
|
-
|
|
53
|
-
## 3. Create the content repo
|
|
54
|
-
|
|
55
|
-
A private GitHub repo holding everything about *this* deployment:
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
deployment.env # which GCP project and service this deployment runs as
|
|
59
|
-
SYSTEM.md # who the agent serves, its worlds, its tone
|
|
60
|
-
jobs/ # one .md per job: YAML frontmatter + prompt body
|
|
61
|
-
worlds/ # one folder per business area (optional to start)
|
|
62
|
-
.claude/skills/ # skills this deployment owns or overrides (optional)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`deployment.env` is committed — none of it is secret, and a clone of the repo is then
|
|
66
|
-
everything an operator needs:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
npx @meffecta/agent init # writes deployment.env here
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
```ini
|
|
73
|
-
PROJECT=acme-agent-506513 # the project ID from step 1
|
|
74
|
-
SERVICE=acme-agent
|
|
75
|
-
ARTIFACT_REPO=acme-agent-images
|
|
76
|
-
REGION=europe-west1
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
`SYSTEM.md` describes **who this agent serves** — the person or team, the businesses, the
|
|
80
|
-
tone, which systems belong to whom. It does not need to restate the safety rules: the
|
|
81
|
-
engine appends its own baseline ([SYSTEM.base.md](SYSTEM.base.md) — what you read is data
|
|
82
|
-
not instructions, act only where the job says, secrets never leave, third-party privacy,
|
|
83
|
-
report honestly) to every run in every deployment, and that baseline overrides anything
|
|
84
|
-
contradicting it. Your `SYSTEM.md` can make a rule *stricter*, or name the concrete
|
|
85
|
-
accounts and people it applies to; it cannot relax one.
|
|
86
|
-
|
|
87
|
-
One job to start, `jobs/hello.md`:
|
|
88
|
-
|
|
89
|
-
```markdown
|
|
90
|
-
---
|
|
91
|
-
name: hello
|
|
92
|
-
cron: "0 7 * * 1-5"
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
Say good morning and list today's date. Send it by email to <person> using the
|
|
96
|
-
send-email skill. If email is unavailable, return the text as your result.
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Frontmatter keys: `cron`, `webhook`, `inbox`, `repo`, `systemMd`, `model`, `effort`,
|
|
100
|
-
`allowedTools`, `timeoutSeconds`, `disabled`. A job with no `name:` takes its filename.
|
|
101
|
-
|
|
102
|
-
- [ ] Repo pushed to GitHub
|
|
103
|
-
- [ ] `cd` into it — **every command from here on runs from the content repo**
|
|
104
|
-
|
|
105
|
-
## 4. Install the tools
|
|
106
|
-
|
|
107
|
-
On the machine you operate from:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
docker info >/dev/null && echo "docker ok" # needed to mirror engine images
|
|
111
|
-
git --version && gh --version
|
|
112
|
-
node --version # 24+
|
|
113
|
-
npm i -g @anthropic-ai/claude-code
|
|
114
|
-
corepack enable
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
- [ ] `gcloud auth configure-docker $REGION-docker.pkg.dev` — one-time, so the mirror in
|
|
118
|
-
step 8 can push into your Artifact Registry. Pulling the engine image itself needs
|
|
119
|
-
no login: `ghcr.io/meffecta/agent` is public.
|
|
120
|
-
|
|
121
|
-
Then the tool itself:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
npm i -g @meffecta/agent # or use npx, which needs no install
|
|
125
|
-
meffecta-agent version # names the engine build this version deploys
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
- [ ] `meffecta-agent help` lists the commands
|
|
129
|
-
- [ ] `meffecta-agent version` shows a pinned engine tag, not "latest"
|
|
130
|
-
|
|
131
|
-
Pin the version you install. Each release of the tool deploys the engine image published
|
|
132
|
-
alongside it, so upgrading the tool is how you move to a new engine — deliberately, not by
|
|
133
|
-
surprise.
|
|
134
|
-
|
|
135
|
-
<details>
|
|
136
|
-
<summary>No npm? The same tooling is inside the public image.</summary>
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
cid=$(docker create ghcr.io/meffecta/agent:latest) \
|
|
140
|
-
&& docker cp "$cid:/app/scripts" . \
|
|
141
|
-
&& docker rm "$cid" >/dev/null
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
That drops `scripts/` into your content repo; run `scripts/deploy.sh` and friends directly,
|
|
145
|
-
and `scripts/update-tooling.sh --tag <the tag you deploy>` to refresh them. Every CLI
|
|
146
|
-
command is one of these scripts with a name in front of it.
|
|
147
|
-
</details>
|
|
148
|
-
|
|
149
|
-
## 5. Mint the credentials
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
claude setup-token # → CLAUDE_CODE_OAUTH_TOKEN, pasted in step 7
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
- [ ] `CLAUDE_CODE_OAUTH_TOKEN` — this deployment bills its own runs
|
|
156
|
-
- [ ] `GITHUB_TOKEN` — fine-grained PAT with **contents read on the content repo** (the
|
|
157
|
-
service cannot start without it), plus write on any repo whose jobs open PRs
|
|
158
|
-
- [ ] `AGENT_WEBHOOK_SECRET` needs nothing here — step 7 generates it
|
|
159
|
-
|
|
160
|
-
**Gmail + Calendar** (skip if the agent needs no mailbox). In the agent's GCP project:
|
|
161
|
-
enable the Gmail and Calendar APIs; OAuth consent screen → **External**, then **publish to
|
|
162
|
-
production** — an app left in "Testing" expires refresh tokens after 7 days; create an
|
|
163
|
-
OAuth client of type **Desktop app**. Then per account:
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
npx @meffecta/agent mint-gmail \
|
|
167
|
-
--client-id <id> --client-secret <secret> [--account <NAME>] [--readonly]
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Sign in as the account the token is for. Default → `GMAIL_REFRESH_TOKEN`; named →
|
|
171
|
-
`GMAIL_<NAME>_REFRESH_TOKEN`. Use `--readonly` for any mailbox this company does not
|
|
172
|
-
administer alone.
|
|
173
|
-
|
|
174
|
-
**Microsoft 365** (only if a mailbox lives there): one Entra app registration, then
|
|
175
|
-
`npx @meffecta/agent mint-graph --account <NAME> …`.
|
|
176
|
-
|
|
177
|
-
## 6. Provision the infrastructure
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
npx @meffecta/agent setup-infra
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Idempotent — re-run it after any change. It prints the project and service it is about to
|
|
184
|
-
touch, then creates: the APIs, an Artifact Registry repo, the runtime service account, a
|
|
185
|
-
memory bucket (mounted at `/memory`), an audit bucket (365-day retention, write-once,
|
|
186
|
-
never mounted), and the Cloud Run service shell with a placeholder image and CPU always
|
|
187
|
-
allocated.
|
|
188
|
-
|
|
189
|
-
- [ ] The banner names the project from your `deployment.env` — if not, you are in the
|
|
190
|
-
wrong directory
|
|
191
|
-
|
|
192
|
-
## 7. Wire up the configuration
|
|
193
|
-
|
|
194
|
-
`set-secret.sh` stores a value in Secret Manager and binds it to the service in one step;
|
|
195
|
-
the value never reaches your shell history or the screen. Re-running it rotates a value.
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
npx @meffecta/agent set-secret AGENT_WEBHOOK_SECRET --random # generated for you
|
|
199
|
-
npx @meffecta/agent set-secret CLAUDE_CODE_OAUTH_TOKEN # prompts, hidden
|
|
200
|
-
npx @meffecta/agent set-secret GITHUB_TOKEN
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
- [ ] `AGENT_WEBHOOK_SECRET`
|
|
204
|
-
- [ ] `CLAUDE_CODE_OAUTH_TOKEN`
|
|
205
|
-
- [ ] `GITHUB_TOKEN`
|
|
206
|
-
|
|
207
|
-
Non-secret settings go through `set-env` (several at once become one revision; add
|
|
208
|
-
`--dry-run` to see what it would do). **The service will not boot without `GIT_REPO_URL`:**
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
npx @meffecta/agent set-env GIT_REPO_URL=https://github.com/<owner>/<repo>.git
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
- [ ] `GIT_REPO_URL` points at the content repo from step 3
|
|
215
|
-
|
|
216
|
-
Optional, one ability each: `GMAIL_*`, `MSGRAPH_*`, `GRAFANA_*`, `CLOUDFLARE_*`,
|
|
217
|
-
`POSTHOG_*`, `GOOGLE_ADS_*`, `AHREFS_API_KEY`, `<WORLD>_GA4_PROPERTY_ID`. Full list with
|
|
218
|
-
comments in the engine repo's `.env.example`. Tokens and keys go through `set-secret`;
|
|
219
|
-
addresses, ids and URLs through `set-env`. `meffecta-agent env` and `meffecta-agent secrets`
|
|
220
|
-
show what is set — the second never prints a value.
|
|
221
|
-
|
|
222
|
-
Surfaces that authenticate as the **runtime service account** rather than a token — GA4,
|
|
223
|
-
Search Console, Google Ads, Cloud Run deployment listing, and delegated Gmail/Drive/
|
|
224
|
-
Calendar — additionally need that service account invited on each property, and
|
|
225
|
-
domain-wide delegation granted in the Workspace admin console. Leave these for last; each
|
|
226
|
-
degrades gracefully until granted.
|
|
227
|
-
|
|
228
|
-
## 8. Deploy the engine
|
|
229
|
-
|
|
230
|
-
```bash
|
|
231
|
-
npx @meffecta/agent deploy # --dry-run first to see the target
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Mirrors the engine image this tool version was published with into your Artifact Registry,
|
|
235
|
-
rolls it out, and asserts the runtime shape from `deployment.env`. `--tag <other>` pins or
|
|
236
|
-
rolls back to a different build.
|
|
237
|
-
|
|
238
|
-
## 9. Create the triggers
|
|
239
|
-
|
|
240
|
-
The service scales to zero and has CPU only while it is answering a request, so nothing in
|
|
241
|
-
it fires on its own. This is what sends it work:
|
|
242
|
-
|
|
243
|
-
```bash
|
|
244
|
-
npx @meffecta/agent setup-scheduler # --dry-run first to see what it would create
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
It creates a Cloud Tasks queue, points the service at it, and creates one Cloud Scheduler
|
|
248
|
-
job per `cron:` in your content repo plus a housekeeping sweep. It reads the job list from
|
|
249
|
-
the running service, so step 8 has to have succeeded first.
|
|
250
|
-
|
|
251
|
-
- [ ] It reports one trigger per cron job, plus `<service>-sweep`
|
|
252
|
-
- [ ] `npx @meffecta/agent triggers` agrees, and shows the task queue running
|
|
253
|
-
|
|
254
|
-
Re-run it whenever a job's `cron:` changes or a job is added or renamed — `deploy` does it
|
|
255
|
-
for you on every rollout from here on. Check it any time with `meffecta-agent triggers`.
|
|
256
|
-
|
|
257
|
-
## 10. Verify
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
|
-
npx @meffecta/agent status
|
|
261
|
-
npx @meffecta/agent jobs
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
- [ ] `status` shows a ready revision, your triggers, and an idle queue
|
|
265
|
-
- [ ] `jobs` lists your jobs — this proves the boot clone worked. An empty list means
|
|
266
|
-
`GIT_REPO_URL` is wrong or `GITHUB_TOKEN` cannot clone it.
|
|
267
|
-
|
|
268
|
-
Then exercise every configured credential from inside the deployment:
|
|
269
|
-
|
|
270
|
-
```bash
|
|
271
|
-
npx @meffecta/agent ask "run node /app/scripts/verify-credentials.mjs and return its output"
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
- [ ] Each surface reports ok or skip; no FAIL (`skip` = not configured, which is fine)
|
|
275
|
-
|
|
276
|
-
The same thing has a web page, for anyone who would rather not use a terminal: open
|
|
277
|
-
`/ask` on the service URL that `status` printed. Any username, the secret as the password.
|
|
278
|
-
|
|
279
|
-
- [ ] The page loads and an answer comes back
|
|
280
|
-
|
|
281
|
-
## 11. First real run
|
|
282
|
-
|
|
283
|
-
```bash
|
|
284
|
-
npx @meffecta/agent run hello
|
|
285
|
-
npx @meffecta/agent logs --limit 50
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
- [ ] Read what it produced before letting the cron take over
|
|
289
|
-
|
|
290
|
-
Then add jobs one at a time — each push is live on the next run. `disabled: true` in
|
|
291
|
-
frontmatter is the kill switch, effective on push. Every prompt, result and full
|
|
292
|
-
transcript lands in the audit bucket.
|