@aitne-sh/aitne 0.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/LICENSE +21 -0
- package/README.md +464 -0
- package/agent-assets/agent-profiles/_safety.md +26 -0
- package/agent-assets/agent-profiles/conversational.md +33 -0
- package/agent-assets/agent-profiles/docs-qa.md +24 -0
- package/agent-assets/agent-profiles/observer.md +28 -0
- package/agent-assets/agent-profiles/profile-importer.md +63 -0
- package/agent-assets/agent-profiles/proxy.md +28 -0
- package/agent-assets/agent-profiles/routine.md +16 -0
- package/agent-assets/agent-profiles/task.md +18 -0
- package/agent-assets/docs/concepts/agent-day.md +88 -0
- package/agent-assets/docs/concepts/auth-health.md +75 -0
- package/agent-assets/docs/concepts/backends-and-tiers.md +126 -0
- package/agent-assets/docs/concepts/costs-and-quotas.md +103 -0
- package/agent-assets/docs/concepts/delegated-mode.md +223 -0
- package/agent-assets/docs/concepts/memory-model.md +118 -0
- package/agent-assets/docs/concepts/observations.md +80 -0
- package/agent-assets/docs/concepts/process-keys.md +89 -0
- package/agent-assets/docs/concepts/routines.md +108 -0
- package/agent-assets/docs/concepts/safety-and-execution.md +109 -0
- package/agent-assets/docs/concepts/safety-model.md +279 -0
- package/agent-assets/docs/concepts/skills.md +100 -0
- package/agent-assets/docs/features/integrations/calendar.md +92 -0
- package/agent-assets/docs/features/integrations/git.md +95 -0
- package/agent-assets/docs/features/integrations/github.md +170 -0
- package/agent-assets/docs/features/integrations/mail.md +106 -0
- package/agent-assets/docs/features/integrations/notion.md +69 -0
- package/agent-assets/docs/features/integrations/obsidian.md +71 -0
- package/agent-assets/docs/features/lifestyle/git.md +178 -0
- package/agent-assets/docs/features/lifestyle/reading.md +93 -0
- package/agent-assets/docs/features/lifestyle/receipts.md +71 -0
- package/agent-assets/docs/features/lifestyle/travel-bookings.md +44 -0
- package/agent-assets/docs/features/lifestyle/travel-time.md +52 -0
- package/agent-assets/docs/features/memory-files/agent-journal.md +105 -0
- package/agent-assets/docs/features/memory-files/projects.md +56 -0
- package/agent-assets/docs/features/memory-files/roadmap.md +61 -0
- package/agent-assets/docs/features/memory-files/schedule.md +112 -0
- package/agent-assets/docs/features/memory-files/today.md +73 -0
- package/agent-assets/docs/features/memory-files/user-profile.md +81 -0
- package/agent-assets/docs/features/messaging/dashboard-chat.md +93 -0
- package/agent-assets/docs/features/messaging/discord.md +50 -0
- package/agent-assets/docs/features/messaging/overview.md +111 -0
- package/agent-assets/docs/features/messaging/pairing-and-magic-phrase.md +69 -0
- package/agent-assets/docs/features/messaging/slack.md +51 -0
- package/agent-assets/docs/features/messaging/telegram.md +63 -0
- package/agent-assets/docs/features/messaging/whatsapp.md +48 -0
- package/agent-assets/docs/features/operations/activity-and-conversations.md +105 -0
- package/agent-assets/docs/features/operations/approvals.md +58 -0
- package/agent-assets/docs/features/operations/backend-routing.md +62 -0
- package/agent-assets/docs/features/operations/cost-tracking.md +59 -0
- package/agent-assets/docs/features/operations/notifications.md +69 -0
- package/agent-assets/docs/features/operations/quiet-hours.md +106 -0
- package/agent-assets/docs/features/operations/schedule-approaching.md +60 -0
- package/agent-assets/docs/features/routines/custom-routines.md +101 -0
- package/agent-assets/docs/features/routines/evening-review.md +81 -0
- package/agent-assets/docs/features/routines/hourly-check.md +85 -0
- package/agent-assets/docs/features/routines/monthly-review.md +65 -0
- package/agent-assets/docs/features/routines/morning-routine.md +123 -0
- package/agent-assets/docs/features/routines/weekly-review.md +70 -0
- package/agent-assets/docs/getting-started/01-what-is-this.md +192 -0
- package/agent-assets/docs/getting-started/02-first-steps.md +80 -0
- package/agent-assets/docs/getting-started/03-what-can-this-do.md +110 -0
- package/agent-assets/docs/getting-started/04-first-day.md +287 -0
- package/agent-assets/docs/glossary.md +116 -0
- package/agent-assets/docs/guides/add-a-custom-routine.md +71 -0
- package/agent-assets/docs/guides/backup-and-restore.md +54 -0
- package/agent-assets/docs/guides/change-which-model-handles-x.md +47 -0
- package/agent-assets/docs/guides/connect-a-new-mail-account.md +59 -0
- package/agent-assets/docs/guides/import-knowledge-file.md +275 -0
- package/agent-assets/docs/guides/install-and-run.md +72 -0
- package/agent-assets/docs/guides/migrate-machines.md +52 -0
- package/agent-assets/docs/guides/pause-the-agent.md +65 -0
- package/agent-assets/docs/guides/reinstall-cleanly.md +52 -0
- package/agent-assets/docs/guides/setup-wizard.md +107 -0
- package/agent-assets/docs/guides/switch-default-backend.md +60 -0
- package/agent-assets/docs/reference/api.md +51 -0
- package/agent-assets/docs/reference/cli-commands.md +121 -0
- package/agent-assets/docs/reference/config.md +74 -0
- package/agent-assets/docs/reference/disallowed-tools.md +76 -0
- package/agent-assets/docs/reference/keyboard-shortcuts.md +39 -0
- package/agent-assets/docs/reference/process-keys.md +59 -0
- package/agent-assets/docs/reference/skills.md +50 -0
- package/agent-assets/docs/troubleshooting/auth-failed.md +57 -0
- package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +55 -0
- package/agent-assets/docs/troubleshooting/fallback-keeps-firing.md +54 -0
- package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +53 -0
- package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +75 -0
- package/agent-assets/docs/troubleshooting/observation-not-detected.md +57 -0
- package/agent-assets/docs/troubleshooting/quota-exhausted.md +57 -0
- package/agent-assets/optimizer-skills/drift-analysis/SKILL.md +75 -0
- package/agent-assets/optimizer-skills/knowledge-map/SKILL.md +71 -0
- package/agent-assets/optimizer-skills/skill-curation/SKILL.md +108 -0
- package/agent-assets/project-doc-templates/git-repo.md +21 -0
- package/agent-assets/project-doc-templates/project.md +38 -0
- package/agent-assets/skills/attach/SKILL.md +104 -0
- package/agent-assets/skills/context/SKILL.md +257 -0
- package/agent-assets/skills/context/curation.json +37 -0
- package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +13 -0
- package/agent-assets/skills/context/seeds/frontmatter-requirements.seed.json +40 -0
- package/agent-assets/skills/docs-search/SKILL.md +176 -0
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +369 -0
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +349 -0
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +347 -0
- package/agent-assets/skills/external-services/SKILL.md +371 -0
- package/agent-assets/skills/mail/SKILL.delegated.claude.md +284 -0
- package/agent-assets/skills/mail/SKILL.delegated.codex.md +261 -0
- package/agent-assets/skills/mail/SKILL.delegated.gemini.md +255 -0
- package/agent-assets/skills/mail/SKILL.md +313 -0
- package/agent-assets/skills/mail/references/errors.md +17 -0
- package/agent-assets/skills/mail/references/providers.md +40 -0
- package/agent-assets/skills/mail/references/query-grammar.md +24 -0
- package/agent-assets/skills/management-policy/SKILL.md +307 -0
- package/agent-assets/skills/management-policy/curation.json +13 -0
- package/agent-assets/skills/management-policy/seeds/policy-file-shape.seed.json +16 -0
- package/agent-assets/skills/management-task-modify/SKILL.md +202 -0
- package/agent-assets/skills/management-task-register/SKILL.md +330 -0
- package/agent-assets/skills/management-task-stop/SKILL.md +166 -0
- package/agent-assets/skills/notify/SKILL.md +196 -0
- package/agent-assets/skills/notion/SKILL.delegated.claude.md +254 -0
- package/agent-assets/skills/notion/SKILL.delegated.codex.md +195 -0
- package/agent-assets/skills/notion/SKILL.delegated.gemini.md +194 -0
- package/agent-assets/skills/notion/SKILL.md +86 -0
- package/agent-assets/skills/observations/SKILL.md +234 -0
- package/agent-assets/skills/observations/curation.json +13 -0
- package/agent-assets/skills/observations/seeds/source-namespacing.seed.json +20 -0
- package/agent-assets/skills/project-doc/SKILL.md +86 -0
- package/agent-assets/skills/project-doc/curation.json +21 -0
- package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +25 -0
- package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +20 -0
- package/agent-assets/skills/reading/SKILL.md +198 -0
- package/agent-assets/skills/reading/references/reading-taste.md +197 -0
- package/agent-assets/skills/receipts/SKILL.md +134 -0
- package/agent-assets/skills/roadmap/SKILL.md +276 -0
- package/agent-assets/skills/roadmap/curation.json +13 -0
- package/agent-assets/skills/roadmap/references/horizon-tags.md +40 -0
- package/agent-assets/skills/roadmap/references/preparation-timeline.md +47 -0
- package/agent-assets/skills/roadmap/seeds/entry-types.seed.json +16 -0
- package/agent-assets/skills/schedule/SKILL.md +228 -0
- package/agent-assets/skills/scheduled-managed-task/SKILL.md +392 -0
- package/agent-assets/skills/today/SKILL.md +198 -0
- package/agent-assets/skills/today/curation.json +21 -0
- package/agent-assets/skills/today/seeds/agent-notes-flavors.seed.json +17 -0
- package/agent-assets/skills/today/seeds/section-shape.seed.json +17 -0
- package/agent-assets/skills/travel/SKILL.md +132 -0
- package/agent-assets/skills/travel-time/SKILL.md +149 -0
- package/agent-assets/skills/user-interview/SKILL.md +323 -0
- package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +94 -0
- package/agent-assets/skills/user-profile/SKILL.md +210 -0
- package/agent-assets/skills/user-profile/curation.json +29 -0
- package/agent-assets/skills/user-profile/seeds/learned-context-format.seed.json +14 -0
- package/agent-assets/skills/user-profile/seeds/routing-table.seed.json +53 -0
- package/agent-assets/skills/user-profile/seeds/topic-files.seed.json +27 -0
- package/agent-assets/task-flows/dashboard.docs_qa.md +43 -0
- package/agent-assets/task-flows/default.md +11 -0
- package/agent-assets/task-flows/git.branch.created.md +25 -0
- package/agent-assets/task-flows/git.lifecycle.poll.md +52 -0
- package/agent-assets/task-flows/git.local_ahead.stale.md +34 -0
- package/agent-assets/task-flows/git.merge_to_default.md +30 -0
- package/agent-assets/task-flows/git.project.refresh_architecture.md +100 -0
- package/agent-assets/task-flows/git.project.retemplate.md +73 -0
- package/agent-assets/task-flows/git.push.detected.md +32 -0
- package/agent-assets/task-flows/git.push.force_pushed.md +36 -0
- package/agent-assets/task-flows/git.tag.created.md +24 -0
- package/agent-assets/task-flows/github.assigned.md +43 -0
- package/agent-assets/task-flows/github.pull_request.review_requested.md +57 -0
- package/agent-assets/task-flows/github.security_alert.md +45 -0
- package/agent-assets/task-flows/github.workflow_run.failed.md +57 -0
- package/agent-assets/task-flows/knowledge.import.md +161 -0
- package/agent-assets/task-flows/message.received.dm.md +142 -0
- package/agent-assets/task-flows/message.received.dm_first.md +117 -0
- package/agent-assets/task-flows/message.received.md +14 -0
- package/agent-assets/task-flows/routine.custom.md +38 -0
- package/agent-assets/task-flows/routine.evening_review.md +323 -0
- package/agent-assets/task-flows/routine.hourly_check.delegated.claude.md +405 -0
- package/agent-assets/task-flows/routine.hourly_check.delegated.codex.md +400 -0
- package/agent-assets/task-flows/routine.hourly_check.delegated.gemini.md +404 -0
- package/agent-assets/task-flows/routine.hourly_check.md +184 -0
- package/agent-assets/task-flows/routine.hourly_check.triage.md +93 -0
- package/agent-assets/task-flows/routine.monthly_review.md +250 -0
- package/agent-assets/task-flows/routine.morning_routine.md +300 -0
- package/agent-assets/task-flows/routine.morning_routine_initial.md +184 -0
- package/agent-assets/task-flows/routine.roadmap_refresh.md +275 -0
- package/agent-assets/task-flows/routine.today_refresh.md +172 -0
- package/agent-assets/task-flows/routine.user_profile_sweep.md +242 -0
- package/agent-assets/task-flows/routine.weekly_review.md +247 -0
- package/agent-assets/task-flows/schedule.approaching.md +124 -0
- package/agent-assets/task-flows/scheduled.dm.md +391 -0
- package/agent-assets/task-flows/scheduled.task.md +141 -0
- package/agent-assets/task-flows/setup.initial.md +277 -0
- package/agent-assets/task-flows/setup.update.md +53 -0
- package/agent-assets/templates/README.md +85 -0
- package/agent-assets/templates/_index.md +39 -0
- package/agent-assets/templates/_manifest.json +103 -0
- package/agent-assets/templates/agent/journal.md +10 -0
- package/agent-assets/templates/agent/profile-questions.md +74 -0
- package/agent-assets/templates/context-index.md +42 -0
- package/agent-assets/templates/dossiers/_index.md +22 -0
- package/agent-assets/templates/dossiers/evening.md +23 -0
- package/agent-assets/templates/dossiers/hourly.md +23 -0
- package/agent-assets/templates/dossiers/monthly.md +23 -0
- package/agent-assets/templates/dossiers/morning.md +23 -0
- package/agent-assets/templates/dossiers/roadmap.md +23 -0
- package/agent-assets/templates/dossiers/weekly.md +23 -0
- package/agent-assets/templates/projects/_active.base +14 -0
- package/agent-assets/templates/projects/_index.md +29 -0
- package/agent-assets/templates/roadmap.md +15 -0
- package/agent-assets/templates/routines/_index.md +20 -0
- package/agent-assets/templates/routines/evening.md +22 -0
- package/agent-assets/templates/routines/hourly.md +30 -0
- package/agent-assets/templates/routines/monthly.md +25 -0
- package/agent-assets/templates/routines/morning.md +26 -0
- package/agent-assets/templates/routines/weekly.md +23 -0
- package/agent-assets/templates/rules/_index.md +19 -0
- package/agent-assets/templates/rules/journal-export.md +41 -0
- package/agent-assets/templates/rules/journal-format.md +61 -0
- package/agent-assets/templates/rules/management.md +48 -0
- package/agent-assets/templates/rules/mcp.md +40 -0
- package/agent-assets/templates/rules/policies/_index.md +22 -0
- package/agent-assets/templates/rules/redaction.md +30 -0
- package/agent-assets/templates/today.md +13 -0
- package/agent-assets/templates/user/_index.md +16 -0
- package/agent-assets/templates/user/expertise.md +7 -0
- package/agent-assets/templates/user/goals.md +7 -0
- package/agent-assets/templates/user/people.md +7 -0
- package/agent-assets/templates/user/personal.md +7 -0
- package/agent-assets/templates/user/profile.md +28 -0
- package/agent-assets/templates/user/work.md +7 -0
- package/bin/aitne.mjs +1096 -0
- package/package.json +78 -0
- package/personal-agent.mjs +39 -0
- package/scripts/browser.mjs +99 -0
- package/scripts/check-redaction-coverage.mjs +109 -0
- package/scripts/commands/audit.mjs +309 -0
- package/scripts/commands/doctor.mjs +437 -0
- package/scripts/commands/open.mjs +40 -0
- package/scripts/commands/setup.mjs +21 -0
- package/scripts/commands/uninstall.mjs +114 -0
- package/scripts/commands/update.mjs +96 -0
- package/scripts/commands/version.mjs +62 -0
- package/scripts/commands.md +0 -0
- package/scripts/lib/sqlite-loader.mjs +49 -0
- package/scripts/message-discipline-digest.mjs +535 -0
- package/scripts/poc/google-connector-inheritance/REPORT.md +197 -0
- package/scripts/poc/google-connector-inheritance/claude-sdk-probe.mjs +79 -0
- package/scripts/remint-roadmap-ids.mjs +257 -0
- package/scripts/rm-paths.mjs +22 -0
- package/scripts/run-node.mjs +223 -0
- package/scripts/smoke-obsidian-api.mjs +166 -0
- package/scripts/start.mjs +160 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: external-services
|
|
3
|
+
description: Load for calendar work (Google Calendar, Outlook Calendar, OR Apple Calendar / iCloud), the user's external Obsidian vault, GitHub, or user-authored Skills management. Mail lives in `mail`; Notion in `notion`; one-shot and recurring scheduling in `schedule`.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(curl *)
|
|
6
|
+
- Bash(jq *)
|
|
7
|
+
- Read
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# External Services API Reference
|
|
11
|
+
|
|
12
|
+
Base URL: `http://localhost:8321`. All calls via `curl -s` with `Content-Type: application/json` on POST/PATCH/PUT. URL-encode spaces in paths.
|
|
13
|
+
|
|
14
|
+
## Source of Truth (READ THIS FIRST)
|
|
15
|
+
|
|
16
|
+
Two adjacent files declare where the user's data lives — read both before
|
|
17
|
+
routing any external-service call.
|
|
18
|
+
|
|
19
|
+
1. **`rules/management.md` → `## Source of Truth`** carries durable
|
|
20
|
+
user-authored answers ("Schedule = Google Calendar", "Tasks = Notion",
|
|
21
|
+
etc.). This is the authoritative routing table.
|
|
22
|
+
2. **`~/.personal-agent/integrations.md` → `## Note Sources`** is the
|
|
23
|
+
daemon-rendered snapshot of where notes are kept (the user's external
|
|
24
|
+
Obsidian vault, plus Notion's mode). When the user asks "check
|
|
25
|
+
obsidian", this section names the path under
|
|
26
|
+
`Obsidian vault (personal): <path>` — use that path with the Obsidian
|
|
27
|
+
skill below. Hand-edits to this section are overwritten on the next
|
|
28
|
+
render; the canonical edit surface is the Note step in setup or
|
|
29
|
+
Settings → Note.
|
|
30
|
+
|
|
31
|
+
The Note Sources block is **read-only** — it advertises configuration
|
|
32
|
+
that lives in `runtime_settings.externalObsidianVaultPath` plus the
|
|
33
|
+
integrations DB. Treat it as a routing hint, not a knob.
|
|
34
|
+
|
|
35
|
+
### Calendar provider routing
|
|
36
|
+
|
|
37
|
+
The user's calendar provider lives in `rules/management.md` → `## Source of Truth` → Schedule row. Read it before every calendar call.
|
|
38
|
+
|
|
39
|
+
| Schedule value in management rules | Use this base path | Backed by |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `Google Calendar` | `/api/calendar/*` | Google Calendar API |
|
|
42
|
+
| `Outlook Calendar` | `/api/calendar/outlook/*` | Microsoft Graph |
|
|
43
|
+
| `Apple Calendar` (or `iCloud`) | `/api/apple-calendar/*` | iCloud CalDAV |
|
|
44
|
+
|
|
45
|
+
**Hard rule**: NEVER cross-call. Calling `/api/calendar/*` while Schedule = Apple Calendar does NOT return empty — it queries the user's separate Google account if one exists, returning the wrong day. Calling `/api/apple-calendar/*` while Schedule = Google Calendar returns 503. Both failure modes are silent at the agent level — only the user notices, in the form of wrong answers.
|
|
46
|
+
|
|
47
|
+
If `rules/management.md` is missing, ambiguous, or names a provider not listed here, **stop and ask the user** rather than guessing. Do not default to Google.
|
|
48
|
+
|
|
49
|
+
The endpoint sets are intentionally near-identical in shape (same JSON for events, same query parameters for listing) so the rest of this skill body documents both at once. Provider-specific differences are flagged inline with **[Apple only]** or **[Google only]**.
|
|
50
|
+
|
|
51
|
+
## Delegation-aware routing for Google Calendar (read before any `/api/calendar/*` call)
|
|
52
|
+
|
|
53
|
+
This body is materialized only in direct mode and same-backend Calendar
|
|
54
|
+
delegation. (Cross-backend Calendar delegation pulls
|
|
55
|
+
`SKILL.delegated.<backend>.md` instead — that variant has its own
|
|
56
|
+
routing prose.) Only **Google Calendar** in this skill is
|
|
57
|
+
integration-gated; Obsidian, GitHub, recurring-schedule CRUD, one-shot
|
|
58
|
+
scheduling, and Skills CRUD remain direct-mode routes regardless of
|
|
59
|
+
Calendar's mode.
|
|
60
|
+
|
|
61
|
+
Read the `<integration_modes>` block injected above. If
|
|
62
|
+
`google_calendar="delegated"` (same-backend), the entire
|
|
63
|
+
`/api/calendar/*` prefix returns `410 {"error": "integration_delegated"}`
|
|
64
|
+
(route-prefix gate). Use the connector tools your session already holds
|
|
65
|
+
natively — `mcp__claude_ai_Google_Calendar__*` (Claude session) or
|
|
66
|
+
`mcp__codex_apps__google_calendar._*` (Codex session).
|
|
67
|
+
|
|
68
|
+
The Calendar section below documents the direct-mode route shapes;
|
|
69
|
+
consult it for tool argument shapes (native MCP tools mirror the route
|
|
70
|
+
JSON), then dispatch through the native connector when delegated or the
|
|
71
|
+
direct route when not.
|
|
72
|
+
|
|
73
|
+
## Shell rules (read before writing curl pipelines)
|
|
74
|
+
|
|
75
|
+
- **JSON post-processing: use `jq`, never `python3`.** `python3` is not in the daemon's allowlist, so `curl ... | python3 -c ...` is denied under `permissionMode: "dontAsk"` and the call silently fails. Use `jq` for all field extraction, filtering, and pretty-printing.
|
|
76
|
+
- **`jq` is restricted**: `--slurpfile`, `--rawfile`, `-L`, and the `env` filter are blocked by the security hook (arbitrary file read / process environment exfiltration). Use only the filter language itself: `.field`, `.array[]`, `select()`, `map()`, `{a, b}`, etc.
|
|
77
|
+
- **`curl` is restricted to `http://localhost:8321`**: connection-override flags (`--connect-to`, `--resolve`, `--config`, `--proxy`) and non-localhost hosts are blocked by the security hook.
|
|
78
|
+
- **For a bare pretty-print**: `curl -s http://localhost:8321/api/health | jq .`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
<!-- service:calendar -->
|
|
83
|
+
## Calendar
|
|
84
|
+
|
|
85
|
+
Google Calendar proxy. Operates on the user's primary calendar (configurable via `calendarId` param).
|
|
86
|
+
|
|
87
|
+
**Timezone rule**: Always include a TZ offset in `start`/`end` dateTime values (e.g. `-04:00`). All-day events use `YYYY-MM-DD` (no TZ needed).
|
|
88
|
+
|
|
89
|
+
**Event status**: GET returns deleted events with `status: "cancelled"` (200, not 404). Always check `status` before acting. The list endpoint automatically excludes cancelled events.
|
|
90
|
+
|
|
91
|
+
### List events
|
|
92
|
+
```bash
|
|
93
|
+
curl -s "http://localhost:8321/api/calendar/events?date=today&days=3"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Get event detail
|
|
97
|
+
```bash
|
|
98
|
+
curl -s "http://localhost:8321/api/calendar/events/abc123eventid"
|
|
99
|
+
```
|
|
100
|
+
**Always GET before PATCH** to see current state and attendees.
|
|
101
|
+
|
|
102
|
+
### Create event (write — Autonomous)
|
|
103
|
+
```bash
|
|
104
|
+
curl -s -X POST "http://localhost:8321/api/calendar/events" \
|
|
105
|
+
-H 'Content-Type: application/json' \
|
|
106
|
+
-d '{"summary": "Team meeting", "start": "2026-04-02T14:00:00-04:00", "end": "2026-04-02T15:00:00-04:00"}'
|
|
107
|
+
```
|
|
108
|
+
Optional: `description`, `location`, `reminders`, `recurrence`, `attendees`, `visibility`. All-day: `YYYY-MM-DD`. Attendees: add `?sendUpdates=all` to notify. RRULE: `RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR`.
|
|
109
|
+
|
|
110
|
+
### Update event (write — Autonomous; commonly on the starter denylist)
|
|
111
|
+
```bash
|
|
112
|
+
curl -s -X PATCH "http://localhost:8321/api/calendar/events/abc123" \
|
|
113
|
+
-H 'Content-Type: application/json' \
|
|
114
|
+
-d '{"start": "2026-04-02T15:00:00-04:00", "end": "2026-04-02T16:00:00-04:00"}'
|
|
115
|
+
```
|
|
116
|
+
For recurring events, use the instance ID to update a single occurrence — never PATCH the master.
|
|
117
|
+
|
|
118
|
+
**ATTENDEES WARNING**: PATCH with `attendees` **replaces the entire list** — it does NOT append. To add one attendee: (1) GET, (2) copy existing, (3) add new, (4) PATCH full list.
|
|
119
|
+
|
|
120
|
+
### Delete event (write — Autonomous; default starter denylist denies it)
|
|
121
|
+
```bash
|
|
122
|
+
curl -s -X DELETE "http://localhost:8321/api/calendar/events/abc123"
|
|
123
|
+
```
|
|
124
|
+
Add `?sendUpdates=all` to notify attendees. Do NOT PATCH a cancelled event.
|
|
125
|
+
|
|
126
|
+
### List calendars
|
|
127
|
+
```bash
|
|
128
|
+
curl -s http://localhost:8321/api/calendar/calendars
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Free/busy query
|
|
132
|
+
```bash
|
|
133
|
+
curl -s -X POST http://localhost:8321/api/calendar/freebusy \
|
|
134
|
+
-H 'Content-Type: application/json' \
|
|
135
|
+
-d '{"timeMin": "2026-04-11T09:00:00-04:00", "timeMax": "2026-04-11T18:00:00-04:00"}'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Calendar error envelope (direct mode)
|
|
139
|
+
|
|
140
|
+
| HTTP | `error` | What it means / what to do |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| 400 | `validation_error` | Bad request shape (e.g. missing `start`/`end`, malformed RRULE). Fix and retry. |
|
|
143
|
+
| 404 | `not_found` | Event id unknown or already deleted. Re-list before retrying. |
|
|
144
|
+
| 410 | `integration_delegated` | Calendar flipped to delegated mode mid-session. This skill body is direct-only — re-read `integrations.md` and use `POST /api/integrations/google_calendar/exec` (cross-backend task mode) or your session backend's native Calendar MCP (the same-backend variant) instead. |
|
|
145
|
+
| 502 | `calendar_error` | Upstream Google API error — `message` carries the API's text. Surface verbatim; do not retry unless clearly transient. |
|
|
146
|
+
| 503 | `calendar_not_configured` | Direct OAuth credentials are missing or the user has disabled Calendar in settings. Tell the user and stop. |
|
|
147
|
+
<!-- /service:calendar -->
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
<!-- service:outlook-calendar -->
|
|
152
|
+
## Outlook Calendar (Microsoft Graph)
|
|
153
|
+
|
|
154
|
+
Use this section **only when `rules/management.md` Schedule = Outlook Calendar**. The provider-routing table at the top of this skill is non-negotiable.
|
|
155
|
+
|
|
156
|
+
v1 is **read-only and on-demand** — there is no Outlook calendar poller, so `schedule.approaching` events do not fire for Outlook calendars (the user's own Outlook clients fill that gap). Write surfaces (create / update / delete) are deferred. If the user asks the agent to schedule or change an Outlook event, tell them you can read the calendar but must defer the write to them.
|
|
157
|
+
|
|
158
|
+
OAuth is **shared with Outlook Mail** via the same MSAL cache row (`mail:outlook:<accountId>`) — if Outlook Mail is configured `direct` and authenticated, calendar reads succeed with no second consent.
|
|
159
|
+
|
|
160
|
+
### List events
|
|
161
|
+
```bash
|
|
162
|
+
curl -s "http://localhost:8321/api/calendar/outlook/events?date=today&days=3"
|
|
163
|
+
```
|
|
164
|
+
Same query params as Google (`date`: `YYYY-MM-DD` or `today`; `days`: 1–90; optional `calendarId`). Returns `{ events: [...], accountId }`.
|
|
165
|
+
|
|
166
|
+
### List calendars
|
|
167
|
+
```bash
|
|
168
|
+
curl -s http://localhost:8321/api/calendar/outlook/calendars
|
|
169
|
+
```
|
|
170
|
+
Returns `{ calendars: [...], accountId }`. The user's primary calendar is marked `primary: true`.
|
|
171
|
+
|
|
172
|
+
### Outlook Calendar error envelope
|
|
173
|
+
|
|
174
|
+
| HTTP | `error` | What it means / what to do |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| 400 | bad query | Malformed `date` or `days` value. |
|
|
177
|
+
| 502 | `calendar_error` | Upstream Microsoft Graph error — `message` carries wire text. |
|
|
178
|
+
| 503 | `outlook_not_configured` | No authenticated Outlook account. Direct OAuth credentials missing. |
|
|
179
|
+
| 503 | `outlook_calendar_disabled` | The user toggled Outlook Calendar off in Settings → Calendar. Tell the user and stop. |
|
|
180
|
+
<!-- /service:outlook-calendar -->
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
<!-- service:apple-calendar -->
|
|
185
|
+
## Apple Calendar (iCloud CalDAV)
|
|
186
|
+
|
|
187
|
+
Use this section **only when `rules/management.md` Schedule = Apple Calendar**. The provider-routing table at the top of this skill is non-negotiable.
|
|
188
|
+
|
|
189
|
+
The route shape mirrors `/api/calendar/*` so prose patterns transfer: list → get → patch / create / delete. Differences are flagged below.
|
|
190
|
+
|
|
191
|
+
### Probe configuration before first use
|
|
192
|
+
```bash
|
|
193
|
+
curl -s http://localhost:8321/api/apple-calendar/status
|
|
194
|
+
# → { "configured": bool, "available": bool }
|
|
195
|
+
```
|
|
196
|
+
- `configured: false` → user has not entered Apple ID + app-specific password yet. Tell the user to open the dashboard's Apple Calendar card (Connections page) and paste a password from `appleid.apple.com` → Sign-In and Security → App-Specific Passwords. **Do not try to read or write events** until `available: true`.
|
|
197
|
+
- `configured: true, available: false` → credentials are stored but iCloud rejected the last connection. Surface verbatim; common cause is the user revoked the app-specific password.
|
|
198
|
+
|
|
199
|
+
### List events
|
|
200
|
+
```bash
|
|
201
|
+
curl -s "http://localhost:8321/api/apple-calendar/events?date=today&days=3"
|
|
202
|
+
```
|
|
203
|
+
Same query params as Google: `date` (`YYYY-MM-DD` or `today`), `days` (max 90). Returns `{ events: [...] }` with the same JSON shape used by the Google route — `id`, `summary`, `start`, `end`, `location`, `description`, `allDay`, `status`, plus two Apple-specific fields:
|
|
204
|
+
- `recurring` (bool) — true for any event in a recurring series.
|
|
205
|
+
- `recurrenceId` (string|null) — populated for an expanded instance of a series.
|
|
206
|
+
|
|
207
|
+
For a recurring instance the `id` is `<UID>__<RECURRENCE-ID>` so you can address a specific occurrence.
|
|
208
|
+
|
|
209
|
+
**Timezones**: dateTime values are emitted in UTC (`Z` suffix). Convert to the user's local timezone before showing them.
|
|
210
|
+
|
|
211
|
+
### Get event detail
|
|
212
|
+
```bash
|
|
213
|
+
curl -s "http://localhost:8321/api/apple-calendar/events/<id>"
|
|
214
|
+
```
|
|
215
|
+
Always GET before PATCH so you see the current summary/start/end.
|
|
216
|
+
|
|
217
|
+
### Create event (write — Autonomous)
|
|
218
|
+
```bash
|
|
219
|
+
curl -s -X POST http://localhost:8321/api/apple-calendar/events \
|
|
220
|
+
-H 'Content-Type: application/json' \
|
|
221
|
+
-d '{"summary": "Team meeting", "start": "2026-04-26T14:00:00+09:00", "end": "2026-04-26T15:00:00+09:00"}'
|
|
222
|
+
```
|
|
223
|
+
Optional: `description`, `location`. **[Apple only]** `attendees`, `reminders`, `recurrence`, `visibility` from the Google shape are accepted by the Zod schema but are silently dropped — iCloud invitations and reminder defaults belong to the user's Apple ID and the agent should not author them. If a user asks for those, tell them and stop.
|
|
224
|
+
|
|
225
|
+
### Update event (write — Autonomous)
|
|
226
|
+
```bash
|
|
227
|
+
curl -s -X PATCH http://localhost:8321/api/apple-calendar/events/<id> \
|
|
228
|
+
-H 'Content-Type: application/json' \
|
|
229
|
+
-d '{"start": "2026-04-26T15:00:00+09:00", "end": "2026-04-26T16:00:00+09:00"}'
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**[Apple only] Recurring-event editing semantics — read before writing**
|
|
233
|
+
- A composite id (one whose suffix matches `__YYYY-MM-DD…`) addresses **one occurrence** of a series. PATCH/DELETE on it returns `501 recurring_instance_unsupported`. To move a single occurrence the user must edit it from Calendar.app.
|
|
234
|
+
- A bare id whose GET returned `recurring: true` is the **series master**. PATCH on the master shifts the **entire series** (every future occurrence moves), and DELETE removes the entire series. Confirm with the user that they intend a series-level edit before issuing the call — agents have historically read "PATCH this event's start" as a single-instance reschedule, which is wrong here.
|
|
235
|
+
- A bare id with `recurring: false` is a normal one-off event — PATCH/DELETE behave as usual.
|
|
236
|
+
- `summary`, `start`, and `end` may be updated independently. Toggling all-day-ness (`YYYY-MM-DD` ↔ `…T…Z`) requires providing **both** `start` and `end` in the same PATCH; the codec rejects partial all-day toggles with `400 validation_error`.
|
|
237
|
+
- Time strings must include a TZ offset (`Z` or `±HH:MM`); naked ISO without offset returns `400 validation_error` — do not interpret a user-stated time as local without an explicit offset.
|
|
238
|
+
|
|
239
|
+
### Delete event (write — Autonomous)
|
|
240
|
+
```bash
|
|
241
|
+
curl -s -X DELETE http://localhost:8321/api/apple-calendar/events/<id>
|
|
242
|
+
```
|
|
243
|
+
Same recurring semantics as PATCH (see the rules block above).
|
|
244
|
+
|
|
245
|
+
### List calendars
|
|
246
|
+
```bash
|
|
247
|
+
curl -s http://localhost:8321/api/apple-calendar/calendars
|
|
248
|
+
# → { "calendars": [{ id, summary, description, primary }, ...] }
|
|
249
|
+
```
|
|
250
|
+
The `id` is an opaque CalDAV URL. The user's primary calendar is marked `primary: true`. To change which calendar create/list reads, see the dashboard Apple Calendar card.
|
|
251
|
+
|
|
252
|
+
### Free/busy query
|
|
253
|
+
```bash
|
|
254
|
+
curl -s -X POST http://localhost:8321/api/apple-calendar/freebusy \
|
|
255
|
+
-H 'Content-Type: application/json' \
|
|
256
|
+
-d '{"timeMin": "2026-04-26T09:00:00Z", "timeMax": "2026-04-26T18:00:00Z"}'
|
|
257
|
+
```
|
|
258
|
+
**[Apple only]** Free-busy is derived from `listEvents` — events with `status: "cancelled"` are excluded. `calendarIds` is ignored (the primary calendar is the only target).
|
|
259
|
+
|
|
260
|
+
### Apple Calendar error envelope
|
|
261
|
+
|
|
262
|
+
| HTTP | `error` | What it means / what to do |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| 400 | `validation_error` | Bad request shape. Fix and retry. |
|
|
265
|
+
| 401 | `auth_failed` | iCloud rejected the credentials. Tell the user to refresh the app-specific password in the dashboard. |
|
|
266
|
+
| 404 | `not_found` | Event id unknown or already deleted. Re-list before retrying. |
|
|
267
|
+
| 501 | `recurring_instance_unsupported` | The id targets a single occurrence of a recurring series — see the PATCH/DELETE notes above. |
|
|
268
|
+
| 502 | `apple_calendar_error` | Upstream iCloud / CalDAV error. `message` carries the wire text. |
|
|
269
|
+
| 503 | `apple_calendar_not_configured` | Credentials missing or last connection failed. Run the status probe above. |
|
|
270
|
+
|
|
271
|
+
### Known gap: no proactive notifications
|
|
272
|
+
|
|
273
|
+
The hourly polling pivot (`schedule.approaching` events, observation deltas) only fires for Google Calendar today. With Apple Calendar selected, on-demand DM queries work but the agent will not proactively warn about an imminent event — the user's own iOS / macOS Calendar.app notifications fill that gap.
|
|
274
|
+
<!-- /service:apple-calendar -->
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
<!-- service:obsidian -->
|
|
279
|
+
## Obsidian (external vault)
|
|
280
|
+
|
|
281
|
+
**Scope**: this skill targets a **separate** Obsidian vault the user maintains
|
|
282
|
+
alongside this app — e.g. a personal knowledge base. It is **not** the agent's
|
|
283
|
+
own primary management store. The agent's primary files (`today.md`,
|
|
284
|
+
`roadmap.md`, `projects/`, `rules/`, `routines/`, `user/`, `agent/`, …) live
|
|
285
|
+
in the primary vault and are reached via `/api/context/*` (see the `context`
|
|
286
|
+
skill). **Never** use this skill to read or write the primary vault.
|
|
287
|
+
|
|
288
|
+
Use this skill when the user asks the agent to look up, append to, or create
|
|
289
|
+
notes inside their external knowledge vault — never for the agent's own
|
|
290
|
+
working state.
|
|
291
|
+
|
|
292
|
+
Full CRUD over the external vault. Requires the Obsidian app running (the
|
|
293
|
+
CLI proxies through it). Omit `.md` extension from paths. All writes are
|
|
294
|
+
Autonomous; the daemon does not DM the owner before/after the call. Call
|
|
295
|
+
`POST /api/notify` yourself when the user would want to know.
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
curl -s http://localhost:8321/api/obsidian/status # external vault availability
|
|
299
|
+
curl -s "http://localhost:8321/api/obsidian/search?q=meeting+notes&limit=10" # search external vault
|
|
300
|
+
curl -s http://localhost:8321/api/obsidian/notes/Daily%20Notes/2026-04-06 # read external note
|
|
301
|
+
curl -s -X POST http://localhost:8321/api/obsidian/notes \
|
|
302
|
+
-H 'Content-Type: application/json' \
|
|
303
|
+
-d '{"name": "Meeting Notes 2026-04-02", "content": "# Meeting\n..."}' # create external note (fails if exists)
|
|
304
|
+
curl -s -X PUT http://localhost:8321/api/obsidian/notes/Projects/ProjectA \
|
|
305
|
+
-H 'Content-Type: application/json' -d '{"content": "# Full body"}' # create-or-overwrite external note
|
|
306
|
+
curl -s -X PATCH http://localhost:8321/api/obsidian/notes \
|
|
307
|
+
-H 'Content-Type: application/json' \
|
|
308
|
+
-d '{"file": "Meeting Notes 2026-04-02", "content": "\n- Action item"}' # append to external note
|
|
309
|
+
curl -s -X PATCH http://localhost:8321/api/obsidian/daily \
|
|
310
|
+
-H 'Content-Type: application/json' -d '{"content": "- [ ] Follow up"}' # append to external daily note
|
|
311
|
+
curl -s -X DELETE http://localhost:8321/api/obsidian/notes/Projects/Old # delete from external vault (moves to trash)
|
|
312
|
+
```
|
|
313
|
+
**Endpoint choice**: Read → GET, Create-only → POST, Edit → PUT, Append → PATCH.
|
|
314
|
+
|
|
315
|
+
If the user's request is really about the agent's own state (today, roadmap,
|
|
316
|
+
projects, journal, rules, routines, user profile), switch to the `context`
|
|
317
|
+
skill and the `/api/context/*` endpoints instead.
|
|
318
|
+
<!-- /service:obsidian -->
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
<!-- service:github -->
|
|
323
|
+
## GitHub
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
curl -s http://localhost:8321/api/github/repos # list watched repos
|
|
327
|
+
curl -s "http://localhost:8321/api/github/pulls?owner=user&repo=repo&state=open" # list PRs
|
|
328
|
+
curl -s -X POST http://localhost:8321/api/github/pulls/comment \
|
|
329
|
+
-H 'Content-Type: application/json' \
|
|
330
|
+
-d '{"owner": "user", "repo": "repo", "pull_number": 42, "comment": "LGTM"}' # comment — Autonomous
|
|
331
|
+
```
|
|
332
|
+
<!-- /service:github -->
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
<!-- service:notion -->
|
|
337
|
+
## Notion
|
|
338
|
+
|
|
339
|
+
Notion operations live in the dedicated `notion` skill — load that when
|
|
340
|
+
the user asks anything Notion-shaped (search, query, read, create,
|
|
341
|
+
update, archive).
|
|
342
|
+
<!-- /service:notion -->
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Scheduling
|
|
347
|
+
|
|
348
|
+
One-shot wake-ups, pre-composed DMs, and recurring agent tasks live in
|
|
349
|
+
the `schedule` skill — load it for `/api/schedule`, `/api/schedule/dm`,
|
|
350
|
+
and `/api/recurring-schedules`. This skill no longer mirrors those
|
|
351
|
+
endpoints; keeping a single source of truth avoids drift across the
|
|
352
|
+
two skills loaded together by morning, hourly, DM, and scheduled
|
|
353
|
+
flows.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Skills Management
|
|
358
|
+
|
|
359
|
+
User-authored skills: `~/.personal-agent/skills/{slug}/SKILL.md`. Built-in skills are read-only (403). Slug: lowercase kebab-case `[a-z0-9][a-z0-9-]*`, 1–64 chars.
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
curl -s http://localhost:8321/api/skills # list all
|
|
363
|
+
curl -s http://localhost:8321/api/skills/todo-digest # read one
|
|
364
|
+
curl -s -X POST http://localhost:8321/api/skills \
|
|
365
|
+
-H 'Content-Type: application/json' \
|
|
366
|
+
-d '{"name": "todo-digest", "description": "Summarize today.md", "content": "# TODO Digest\n...", "allowedTools": ["Bash(curl *)", "Read"]}'
|
|
367
|
+
curl -s -X PUT http://localhost:8321/api/skills/todo-digest \
|
|
368
|
+
-H 'Content-Type: application/json' -d '{"description": "New description"}' # update
|
|
369
|
+
curl -s -X DELETE http://localhost:8321/api/skills/todo-digest # delete
|
|
370
|
+
```
|
|
371
|
+
Always `GET /api/skills` before creating (check name collisions). **Omit frontmatter** from `content` — the API injects it.
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mail
|
|
3
|
+
description: Load when the task touches Gmail and Gmail is in cross-backend delegated mode (DM session is Claude Code; `delegatedBackend` is non-Claude). Gmail accounts route through `POST /api/integrations/gmail/exec`; non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct-mode `/api/mail/*` surface.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(curl *)
|
|
6
|
+
- Read
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Mail (delegated, cross-backend)
|
|
10
|
+
|
|
11
|
+
Gmail is delegated to a different backend (Codex or Gemini). The daemon
|
|
12
|
+
spawns that backend on demand, lets it pick the right MCP tool, and
|
|
13
|
+
returns a schema-validated JSON result. **You describe intent in
|
|
14
|
+
natural language; the daemon picks the tool.** Tool name divergence
|
|
15
|
+
between Codex (`search_emails`), Gemini (`search`) and any custom MCP
|
|
16
|
+
server the user installs is invisible to you.
|
|
17
|
+
|
|
18
|
+
To confirm Gmail's current delegate, read
|
|
19
|
+
`~/.personal-agent/integrations.md` and consult its `delegatedBackend`
|
|
20
|
+
field. The same prose body below works for every delegate.
|
|
21
|
+
|
|
22
|
+
## Non-Gmail accounts keep the direct-mode surface
|
|
23
|
+
|
|
24
|
+
Per-account gating: the `/api/mail/*` 410 only fires when the resolved
|
|
25
|
+
`accountId` is `kind=gmail`. IMAP / Outlook / iCloud / Yahoo accounts
|
|
26
|
+
remain fully reachable through the direct-mode endpoints documented in
|
|
27
|
+
the base `mail` skill body — `GET /api/mail/:acct/messages`,
|
|
28
|
+
`POST /mail/:acct/drafts`, `GET /api/mail/:acct/threads/:threadId`, etc.
|
|
29
|
+
Use `accounts.md` (still materialized for this session) to resolve the
|
|
30
|
+
account and pick the path:
|
|
31
|
+
|
|
32
|
+
| Selected account `kind` | Path |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `gmail` | task: `POST /api/integrations/gmail/exec {task, outputSchema, …}` (this file) |
|
|
35
|
+
| `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/:acct/*` (base body) |
|
|
36
|
+
|
|
37
|
+
Only the Gmail branch leaves the direct-mode surface. Account
|
|
38
|
+
resolution (§1 of the base body), draft-vs-send rules, and reply-thread
|
|
39
|
+
chaining are unchanged for non-Gmail accounts.
|
|
40
|
+
|
|
41
|
+
## Call shape
|
|
42
|
+
|
|
43
|
+
The single endpoint is `POST /api/integrations/gmail/exec`. The body
|
|
44
|
+
takes a natural-language `task` plus an `outputSchema` (Draft-07 JSON
|
|
45
|
+
Schema) the daemon validates the result against. Optional fields
|
|
46
|
+
default safely; raise them only when the task genuinely needs more
|
|
47
|
+
budget.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
curl -s -X POST http://localhost:8321/api/integrations/gmail/exec \
|
|
51
|
+
-H 'Content-Type: application/json' \
|
|
52
|
+
-d '{
|
|
53
|
+
"task": "Search Gmail for unread messages from alice@example.com in the last 7 days. Return up to 10 with sender, subject, snippet, timestamp.",
|
|
54
|
+
"outputSchema": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"required": ["messages"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"messages": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"required": ["from", "subject", "snippet", "ts"],
|
|
63
|
+
"properties": {
|
|
64
|
+
"from": {"type": "string"},
|
|
65
|
+
"subject": {"type": "string"},
|
|
66
|
+
"snippet": {"type": "string"},
|
|
67
|
+
"ts": {"type": "string", "format": "date-time"}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"maxToolCalls": 5,
|
|
74
|
+
"cacheable": true
|
|
75
|
+
}'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Response shape on success:
|
|
79
|
+
|
|
80
|
+
```jsonc
|
|
81
|
+
{
|
|
82
|
+
"result": { "messages": [ ... ] }, // schema-validated parse
|
|
83
|
+
"needsConfirmation": false,
|
|
84
|
+
"confirmationPlan": null,
|
|
85
|
+
"trace": [ /* per-tool-call breakdown — informational */ ],
|
|
86
|
+
"cost": { "tokensInput": ..., "costUsd": ..., "durationMs": ... }
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`outputSchema` is **required** — the subprocess emits exactly one JSON
|
|
91
|
+
object as its final message and the daemon validates it. Schemas
|
|
92
|
+
larger than 4 KB are rejected (`schema_too_large`). Caps default to
|
|
93
|
+
`maxToolCalls=7`, `maxBudgetUsd=0.05`, `timeoutMs=60000` — bump them via
|
|
94
|
+
the request body up to the hard caps (15 / 0.50 / 300000) when a task
|
|
95
|
+
genuinely needs more.
|
|
96
|
+
|
|
97
|
+
## Idempotent reads — `cacheable: true`
|
|
98
|
+
|
|
99
|
+
Pure-read tasks (thread fetches, search summarisations, label lookups)
|
|
100
|
+
should set `cacheable: true` so a repeat invocation within 60s returns
|
|
101
|
+
~5ms from the in-memory LRU. The cache key includes the integration
|
|
102
|
+
state version, so flipping `deniedTools` or `delegatedBackend` purges
|
|
103
|
+
entries automatically. Cache hits still write a `delegated_task.exec`
|
|
104
|
+
audit row with `cost_usd=0` and `detail.cacheHit=true` — accounting
|
|
105
|
+
stays correct.
|
|
106
|
+
|
|
107
|
+
Never set `cacheable: true` on:
|
|
108
|
+
- destructive-confirm second calls (`allowDestructive: true`),
|
|
109
|
+
- tasks that depend on minute-level freshness,
|
|
110
|
+
- any write.
|
|
111
|
+
|
|
112
|
+
## Destructive-confirm dance — `allowDestructive`
|
|
113
|
+
|
|
114
|
+
Default is `false`. The subprocess will not call destructive tools
|
|
115
|
+
(send / delete / batch label mutate / etc.) — instead it returns:
|
|
116
|
+
|
|
117
|
+
```jsonc
|
|
118
|
+
{
|
|
119
|
+
"needsConfirmation": true,
|
|
120
|
+
"confirmationPlan": "I will send a reply to alice@example.com with subject \"Re: Proposal\" and body …"
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Surface `confirmationPlan` to the user verbatim. On their explicit OK,
|
|
125
|
+
re-issue the **same `task` verbatim** with `allowDestructive: true`. Do
|
|
126
|
+
NOT set `cacheable: true` on the second call — the confirmation does
|
|
127
|
+
not extend across cache lifetimes.
|
|
128
|
+
|
|
129
|
+
## Worked examples
|
|
130
|
+
|
|
131
|
+
### Read a whole thread (composition handled by the subprocess)
|
|
132
|
+
|
|
133
|
+
When the active connector lacks a thread-fetch primitive (Gemini), the
|
|
134
|
+
subprocess composes search + per-message get — you don't have to
|
|
135
|
+
think about it.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
curl -s -X POST http://localhost:8321/api/integrations/gmail/exec \
|
|
139
|
+
-H 'Content-Type: application/json' \
|
|
140
|
+
-d '{
|
|
141
|
+
"task": "Fetch every message in Gmail thread <THREAD_ID>. For each message, return from / subject / body / timestamp. Sort by timestamp ascending.",
|
|
142
|
+
"outputSchema": {
|
|
143
|
+
"type": "object",
|
|
144
|
+
"required": ["messages"],
|
|
145
|
+
"properties": {
|
|
146
|
+
"messages": {
|
|
147
|
+
"type": "array",
|
|
148
|
+
"items": {
|
|
149
|
+
"type": "object",
|
|
150
|
+
"required": ["from", "subject", "body", "ts"],
|
|
151
|
+
"properties": {
|
|
152
|
+
"from": {"type": "string"},
|
|
153
|
+
"subject": {"type": "string"},
|
|
154
|
+
"body": {"type": "string"},
|
|
155
|
+
"ts": {"type": "string", "format": "date-time"}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"maxToolCalls": 7,
|
|
162
|
+
"cacheable": true
|
|
163
|
+
}'
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Compose a draft (default-safe, no destructive flag needed)
|
|
167
|
+
|
|
168
|
+
Drafts are inert — the user can review and send from the Gmail web UI.
|
|
169
|
+
Prefer drafts over send.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
curl -s -X POST http://localhost:8321/api/integrations/gmail/exec \
|
|
173
|
+
-H 'Content-Type: application/json' \
|
|
174
|
+
-d '{
|
|
175
|
+
"task": "Compose a Gmail draft replying to message <MESSAGE_ID>. Subject: \"Re: <ORIGINAL_SUBJECT>\". Body: <BODY>. Preserve the RFC-2822 thread (Message-Id + References).",
|
|
176
|
+
"outputSchema": {
|
|
177
|
+
"type": "object",
|
|
178
|
+
"required": ["draftId"],
|
|
179
|
+
"properties": { "draftId": { "type": "string" } }
|
|
180
|
+
},
|
|
181
|
+
"maxToolCalls": 4
|
|
182
|
+
}'
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Send a previously-vetted draft (destructive — confirmation required)
|
|
186
|
+
|
|
187
|
+
Two-step ceremony: first call without `allowDestructive` returns the
|
|
188
|
+
confirmation envelope; on user OK, re-issue with the flag.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
curl -s -X POST http://localhost:8321/api/integrations/gmail/exec \
|
|
192
|
+
-H 'Content-Type: application/json' \
|
|
193
|
+
-d '{
|
|
194
|
+
"task": "Send Gmail draft <DRAFT_ID> as-is. Do not edit the body.",
|
|
195
|
+
"outputSchema": {
|
|
196
|
+
"type": "object",
|
|
197
|
+
"required": ["messageId"],
|
|
198
|
+
"properties": { "messageId": { "type": "string" } }
|
|
199
|
+
},
|
|
200
|
+
"maxToolCalls": 2,
|
|
201
|
+
"allowDestructive": true
|
|
202
|
+
}'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Default deny floor
|
|
206
|
+
|
|
207
|
+
The setup wizard pre-populates `gmail.deniedTools` with the connector's
|
|
208
|
+
destructive defaults (send / batch label mutate / etc.). `/exec`
|
|
209
|
+
honors the deny list: a task that requires a denied tool surfaces as
|
|
210
|
+
`tool_unavailable` (not 403) — the subprocess reports the gap and the
|
|
211
|
+
daemon returns 502. Surface that to the user and ask whether to lift
|
|
212
|
+
the deny before retrying.
|
|
213
|
+
|
|
214
|
+
## Decision rules
|
|
215
|
+
|
|
216
|
+
- **Prefer drafts over send.** Drafts are reversible, send is not. The
|
|
217
|
+
destructive-confirm dance applies to send anyway.
|
|
218
|
+
- **Replies preserve the RFC-2822 chain.** Pin `Message-Id` /
|
|
219
|
+
`References` headers on the draft. The subprocess fetches them from
|
|
220
|
+
the original message regardless of which connector underlies the
|
|
221
|
+
delegate.
|
|
222
|
+
- **The reply account is implicit.** The connector picks the account
|
|
223
|
+
based on its own auth — do not pass an `accountId`.
|
|
224
|
+
- **No `bcc` unless the user explicitly asks for it.**
|
|
225
|
+
- **Bulk operations: ask first.** Mass-mutation intents touch many
|
|
226
|
+
messages in one call. Summarise what you would do (count + criteria)
|
|
227
|
+
and confirm before invoking, even on the destructive-confirm path.
|
|
228
|
+
|
|
229
|
+
## Error envelope
|
|
230
|
+
|
|
231
|
+
`/exec` extends the direct-mode envelope with delegated-mode fields.
|
|
232
|
+
Discriminator: `body.mode === "delegated"`.
|
|
233
|
+
|
|
234
|
+
| HTTP | `error` | retry? | What to do |
|
|
235
|
+
|---|---|---|---|
|
|
236
|
+
| 400 | `validation_error` / `schema_too_large` | no | Fix the request body. |
|
|
237
|
+
| 409 | `mode_mismatch` | no | Gmail isn't delegated, OR your DM backend matches `delegatedBackend`. Re-read `integrations.md` and stop. |
|
|
238
|
+
| 409 | `precondition` | no | Mode/backend was flipped while the call queued. Re-read `integrations.md` and re-plan. |
|
|
239
|
+
| 429 | `task_quota_exhausted` | no | Daily cap reached; wait or surface. |
|
|
240
|
+
| 502 | `parse_error` / `schema_violation` | no (daemon already retried once) | Consider a simpler schema. |
|
|
241
|
+
| 502 | `tool_unavailable` | no | No connector tool fits the intent. Surface the gap to the user. |
|
|
242
|
+
| 502 | `tool_failed` | maybe | Connector tool returned an error. Surface `body.message` verbatim; retry only if clearly transient. |
|
|
243
|
+
| 502 | `auth_error` | no | Connector signed out. Tell the user to re-authenticate. |
|
|
244
|
+
| 502 | `policy_violation` | no | Subprocess attempted a tool outside the per-task allowlist (anti-injection). Surface as anomaly. |
|
|
245
|
+
| 502 | `loop_aborted` | no | `maxToolCalls` exceeded. Likely planning gap; bump the cap or simplify the task. |
|
|
246
|
+
| 502 | `budget_exhausted` | no | `maxBudgetUsd` exceeded. Caller can raise the cap. |
|
|
247
|
+
| 502 | `post_write_format_failure` | no | Write succeeded; formatting failed. The side effect is real — surface to user with the partial trace. |
|
|
248
|
+
| 503 | `delegated_proxy_busy` | yes | Queue saturated. Backoff 3-5s and retry once. |
|
|
249
|
+
| 503 | `task_mode_disabled` | no | Operator turned the kill switch off. Stop. |
|
|
250
|
+
| 504 | `timeout` | yes (1×) | Wall-clock fired. Retry once for simple intents; otherwise surface. |
|
|
251
|
+
| 500 | `subprocess_crashed` | no | Daemon-side defect. Surface and stop. |
|
|
252
|
+
|
|
253
|
+
## Owner notification (opt-in)
|
|
254
|
+
|
|
255
|
+
The daemon does not auto-DM the owner. When you take an action the
|
|
256
|
+
user would want to know about *immediately* — sending an external
|
|
257
|
+
email, archiving a stack, applying a sensitive label — call:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
curl -s -X POST http://localhost:8321/api/notify \
|
|
261
|
+
-H 'Content-Type: application/json' \
|
|
262
|
+
-d '{"message": "Sent reply to alice@example.com (Re: Proposal)"}'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Do not call `/api/notify` for routine reads / drafts / searches. The
|
|
266
|
+
default posture is autonomous; the user's `deniedTools` is the
|
|
267
|
+
hard-stop, on-demand retrospective covers awareness, and `/api/notify`
|
|
268
|
+
is the small hammer for "speak up if I'm about to do something
|
|
269
|
+
unusual."
|
|
270
|
+
|
|
271
|
+
## Cost / retrospective
|
|
272
|
+
|
|
273
|
+
Every `/exec` writes one row to `agent_actions` with
|
|
274
|
+
`action_type='delegated_task.exec'` (token + USD breakdown, parent
|
|
275
|
+
`event_id` / `processKey` attached automatically via session env
|
|
276
|
+
vars). When the user asks what you did:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
curl -s "http://localhost:8321/api/agent/actions?kind=delegated_task.exec&since=2026-04-25T00:00:00Z&limit=50"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Summarise from the returned `actions` array — each row carries
|
|
283
|
+
`detail.task` (the natural-language intent), cost, cache hit flag, and
|
|
284
|
+
timestamp.
|