@letta-ai/letta-code 0.30.4 → 0.30.6
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/dist/agent-presets.js +127 -31
- package/dist/agent-presets.js.map +3 -3
- package/dist/channels-slack.js +1 -1
- package/dist/channels-slack.js.map +3 -3
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/types/agent/create-agent-request.d.ts +55 -25
- package/dist/types/agent/create-agent-request.d.ts.map +1 -1
- package/dist/types/agent/modify.d.ts.map +1 -1
- package/dist/types/agent/subagents/index.d.ts +1 -0
- package/dist/types/agent/subagents/index.d.ts.map +1 -1
- package/dist/types/agent/subagents/manager.d.ts +1 -0
- package/dist/types/agent/subagents/manager.d.ts.map +1 -1
- package/dist/types/agent/subagents/subagent-launcher.d.ts +2 -0
- package/dist/types/agent/subagents/subagent-launcher.d.ts.map +1 -1
- package/dist/types/agent-presets.d.ts +1 -1
- package/dist/types/agent-presets.d.ts.map +1 -1
- package/dist/types/backend/api/client.d.ts +1 -0
- package/dist/types/backend/api/client.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-local-endpoint-provider.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-model-factory.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-models-runtime.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-openai-compatible-provider.d.ts +14 -0
- package/dist/types/backend/dev/pi-openai-compatible-provider.d.ts.map +1 -0
- package/dist/types/backend/dev/pi-provider-registry.d.ts +3 -1
- package/dist/types/backend/dev/pi-provider-registry.d.ts.map +1 -1
- package/dist/types/backend/local/local-provider-auth-store.d.ts +1 -1
- package/dist/types/backend/local/local-provider-auth-store.d.ts.map +1 -1
- package/dist/types/channels/accounts.d.ts.map +1 -1
- package/dist/types/channels/config.d.ts.map +1 -1
- package/dist/types/channels/plugin-types.d.ts +1 -0
- package/dist/types/channels/plugin-types.d.ts.map +1 -1
- package/dist/types/channels/slack/ingress-controller.d.ts.map +1 -1
- package/dist/types/channels/slack/ingress-policy.d.ts +1 -0
- package/dist/types/channels/slack/ingress-policy.d.ts.map +1 -1
- package/dist/types/channels/types.d.ts +2 -0
- package/dist/types/channels/types.d.ts.map +1 -1
- package/dist/types/cli/helpers/error-formatter.d.ts +1 -0
- package/dist/types/cli/helpers/error-formatter.d.ts.map +1 -1
- package/dist/types/cli/helpers/memory-reminder.d.ts +9 -3
- package/dist/types/cli/helpers/memory-reminder.d.ts.map +1 -1
- package/dist/types/providers/byok-providers.d.ts.map +1 -1
- package/dist/types/reflection-settings.d.ts +9 -0
- package/dist/types/reflection-settings.d.ts.map +1 -0
- package/dist/types/runtime-context.d.ts +2 -0
- package/dist/types/runtime-context.d.ts.map +1 -1
- package/dist/types/settings-manager.d.ts +9 -10
- package/dist/types/settings-manager.d.ts.map +1 -1
- package/dist/types/telemetry/index.d.ts +15 -1
- package/dist/types/telemetry/index.d.ts.map +1 -1
- package/dist/types/tools/impl/process_manager.d.ts +1 -0
- package/dist/types/tools/impl/process_manager.d.ts.map +1 -1
- package/dist/types/tools/impl/shell-env.d.ts.map +1 -1
- package/dist/types/tools/impl/task.d.ts +4 -0
- package/dist/types/tools/impl/task.d.ts.map +1 -1
- package/dist/types/tools/toolset.d.ts +1 -0
- package/dist/types/tools/toolset.d.ts.map +1 -1
- package/dist/types/types/protocol_v2.d.ts +5 -0
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/dist/types/websocket/listener/mod-adapter.d.ts +1 -0
- package/dist/types/websocket/listener/mod-adapter.d.ts.map +1 -1
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/letta.js +1919 -1001
- package/package.json +1 -1
- package/scripts/check-test-mock-isolation.js +5 -1
- package/scripts/isolated-unit-tests.json +26 -0
- package/scripts/source-file-size-baseline.json +4 -4
- package/skills/managing-shared-memory/SKILL.md +47 -81
- package/skills/scheduling-tasks/SKILL.md +58 -54
package/package.json
CHANGED
|
@@ -91,7 +91,11 @@ function moduleMatches(moduleSpecifier, suffixes) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
function isRelativeInternalModule(moduleSpecifier) {
|
|
94
|
-
return
|
|
94
|
+
return (
|
|
95
|
+
moduleSpecifier.startsWith("../") ||
|
|
96
|
+
moduleSpecifier.startsWith("./") ||
|
|
97
|
+
moduleSpecifier.startsWith("@/")
|
|
98
|
+
);
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
function lineAndColumn(sourceText, index) {
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"tests": [
|
|
3
|
+
{
|
|
4
|
+
"path": "src/channels/discord-reconcile.test.ts",
|
|
5
|
+
"timeoutMs": 15000,
|
|
6
|
+
"reason": "Mocks the backend client module in beforeAll; the mock leaks into later files in the same process."
|
|
7
|
+
},
|
|
3
8
|
{
|
|
4
9
|
"path": "src/channels/discord-registry.test.ts",
|
|
5
10
|
"timeoutMs": 15000,
|
|
6
11
|
"reason": "Uses a top-level Bun module mock for the backend client."
|
|
7
12
|
},
|
|
13
|
+
{
|
|
14
|
+
"path": "src/channels/slack-registry.test.ts",
|
|
15
|
+
"timeoutMs": 15000,
|
|
16
|
+
"reason": "Uses a top-level Bun module mock for the backend client."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "src/channels/telegram-registry.test.ts",
|
|
20
|
+
"timeoutMs": 15000,
|
|
21
|
+
"reason": "Uses a top-level Bun module mock for the backend client."
|
|
22
|
+
},
|
|
8
23
|
{
|
|
9
24
|
"path": "src/channels/discord-service.test.ts",
|
|
10
25
|
"timeoutMs": 15000,
|
|
@@ -55,6 +70,17 @@
|
|
|
55
70
|
"timeoutMs": 15000,
|
|
56
71
|
"reason": "Mutates the settings singleton, keychain test overrides, HOME, and the secrets service name."
|
|
57
72
|
},
|
|
73
|
+
{
|
|
74
|
+
"path": "src/cli/reflection-worktree-completion.test.ts",
|
|
75
|
+
"timeoutMs": 15000,
|
|
76
|
+
"env": { "LETTA_CODE_TELEM": "1" },
|
|
77
|
+
"reason": "Exercises reflection worktree cleanup telemetry with real Git processes and the shared telemetry singleton."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"path": "src/cli/helpers/reflection-launcher.test.ts",
|
|
81
|
+
"timeoutMs": 15000,
|
|
82
|
+
"reason": "Exercises reflection launch preflight with real Git processes and temporary local-backend environment overrides."
|
|
83
|
+
},
|
|
58
84
|
{
|
|
59
85
|
"path": "src/telemetry/flush-auth.test.ts",
|
|
60
86
|
"timeoutMs": 15000,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"src/backend/local/local-backend.ts": 1014,
|
|
6
6
|
"src/backend/local/local-store.ts": 3594,
|
|
7
7
|
"src/backend/pi-stream-adapter.test.ts": 1304,
|
|
8
|
-
"src/cli/app/AppCoordinator.tsx":
|
|
8
|
+
"src/cli/app/AppCoordinator.tsx": 5188,
|
|
9
9
|
"src/cli/app/AppView.tsx": 1735,
|
|
10
10
|
"src/cli/app/use-approval-flow.ts": 1163,
|
|
11
11
|
"src/cli/app/use-configuration-handlers.ts": 1433,
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"src/cli/mods/local-mod-loader.test.ts": 1043,
|
|
23
23
|
"src/cli/reflection-transcript.test.ts": 1084,
|
|
24
24
|
"src/cli/subcommands/skills.ts": 1264,
|
|
25
|
-
"src/headless.ts":
|
|
25
|
+
"src/headless.ts": 5242,
|
|
26
26
|
"src/hooks/integration.test.ts": 1147,
|
|
27
|
-
"src/index.ts":
|
|
27
|
+
"src/index.ts": 2773,
|
|
28
28
|
"src/mods/learning-harness.ts": 2434,
|
|
29
29
|
"src/mods/mod-engine.test.ts": 2153,
|
|
30
30
|
"src/mods/mod-engine.ts": 1847,
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"src/websocket/listener/commands/memory.ts": 1114,
|
|
47
47
|
"src/websocket/listener/file-commands.ts": 1053,
|
|
48
48
|
"src/websocket/listener/lifecycle.ts": 1052,
|
|
49
|
-
"src/websocket/listener/protocol-inbound.ts":
|
|
49
|
+
"src/websocket/listener/protocol-inbound.ts": 2315,
|
|
50
50
|
"src/websocket/listener/protocol-outbound.ts": 1085
|
|
51
51
|
}
|
|
@@ -5,123 +5,89 @@ description: Create and manage shared memory — git-tracked repositories hosted
|
|
|
5
5
|
|
|
6
6
|
# Managing Shared Memory
|
|
7
7
|
|
|
8
|
-
Shared memory is memory created independently of any single agent, designed to be dynamically attached to or detached from multiple agents. Each unit of shared memory is a **shared memory repository**: a git
|
|
8
|
+
Shared memory is memory created independently of any single agent, designed to be dynamically attached to or detached from multiple agents. Each unit of shared memory is a **shared memory repository**: a git repository hosted on Letta Cloud, owned by your organization rather than by one agent, reachable from any environment (sandboxes, remote machines, sessions).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Shared memory works exactly like your MemFS: attached repositories are real git checkouts on disk, and you read, edit, commit, and push them with ordinary git. The only differences are that each repository has its own projection root (next to your memory directory, not inside it) and its own remote origin, and other agents may be writing to it too.
|
|
11
11
|
|
|
12
12
|
Create a shared memory repository when:
|
|
13
13
|
- You have context an agent should be able to access that doesn't belong in its own MemFS (input files, datasets, docs, working artifacts)
|
|
14
14
|
- Multiple agents need to read or write the same context
|
|
15
15
|
- You want a versioned file store that survives across environments and sessions
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## Working with Files (the normal path)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
When shared memory is attached to you and you're running in a cloud sandbox/environment, it is projected on disk next to your memory directory — each repository at its own projection root:
|
|
19
|
+
Attached shared memory is mounted next to your memory directory, one git checkout per repository:
|
|
22
20
|
|
|
23
21
|
```bash
|
|
24
|
-
ls "$MEMORY_DIR/../"
|
|
25
|
-
cat "$MEMORY_DIR/../<repo-name>/<path>"
|
|
22
|
+
ls "$MEMORY_DIR/../" # attached repositories appear here by name
|
|
23
|
+
cat "$MEMORY_DIR/../<repo-name>/<path>" # read like any file
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## API Operations
|
|
31
|
-
|
|
32
|
-
Shared memory repositories are the `repositories` resource in the Letta API. All operations go through the API using `$LETTA_API_KEY` via the Bash tool. Use `https://api.letta.com` (or `$LETTA_BASE_URL` if set — e.g. when running under Letta Desktop, which proxies auth). Responses are JSON.
|
|
26
|
+
Edit files with your normal file tools, then commit and push with git — the mount's origin and credentials are already configured:
|
|
33
27
|
|
|
34
28
|
```bash
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
cd "$MEMORY_DIR/../<repo-name>"
|
|
30
|
+
git add <files>
|
|
31
|
+
git commit -m "describe the change"
|
|
32
|
+
git push
|
|
37
33
|
```
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# Create
|
|
43
|
-
curl -sS -X POST "$BASE/v1/repositories" -H "$AUTH" -H "Content-Type: application/json" \
|
|
44
|
-
-d '{"name": "shared-inputs"}'
|
|
45
|
-
# → {"id": "repo-...", "name": "shared-inputs", "created_at": ..., "updated_at": ...}
|
|
46
|
-
|
|
47
|
-
# List (paginated)
|
|
48
|
-
curl -sS "$BASE/v1/repositories?limit=50&offset=0" -H "$AUTH"
|
|
49
|
-
# → {"repositories": [...], "has_next_page": false}
|
|
35
|
+
Unlike MemFS, the harness does not auto-push shared memory after turns — a commit you don't push is not visible to other agents or environments. Always push after committing.
|
|
50
36
|
|
|
51
|
-
|
|
52
|
-
curl -sS "$BASE/v1/repositories/{repository_id}" -H "$AUTH"
|
|
37
|
+
To pick up other agents' changes:
|
|
53
38
|
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
```bash
|
|
40
|
+
git -C "$MEMORY_DIR/../<repo-name>" pull --rebase
|
|
56
41
|
```
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
If a push is rejected (another agent pushed first), `git pull --rebase` then push again.
|
|
59
44
|
|
|
60
|
-
|
|
45
|
+
History is ordinary git history:
|
|
61
46
|
|
|
62
47
|
```bash
|
|
63
|
-
|
|
64
|
-
curl -sS "$BASE/v1/repositories/{repository_id}/files?path_prefix=docs/&depth=2" -H "$AUTH"
|
|
65
|
-
# → {"files": [{"path": "docs/a.md", "type": "file"}, ...], "ref": "<sha>"}
|
|
66
|
-
|
|
67
|
-
# Create
|
|
68
|
-
curl -sS -X POST "$BASE/v1/repositories/{repository_id}/files" -H "$AUTH" \
|
|
69
|
-
-H "Content-Type: application/json" \
|
|
70
|
-
-d '{"path": "docs/a.md", "content": "hello"}'
|
|
71
|
-
|
|
72
|
-
# Read (optional: ref for a historical version)
|
|
73
|
-
curl -sS "$BASE/v1/repositories/{repository_id}/files/content?path=docs/a.md" -H "$AUTH"
|
|
74
|
-
# → {"path": "docs/a.md", "content": "hello", "content_sha256": "...", "ref": "..."}
|
|
75
|
-
|
|
76
|
-
# Update content and/or rename. The optional precondition fails the write
|
|
77
|
-
# if the file changed since you last read it (use when multiple agents write).
|
|
78
|
-
curl -sS -X POST "$BASE/v1/repositories/{repository_id}/files/content" -H "$AUTH" \
|
|
79
|
-
-H "Content-Type: application/json" \
|
|
80
|
-
-d '{
|
|
81
|
-
"path": "docs/a.md",
|
|
82
|
-
"content": "updated",
|
|
83
|
-
"new_path": "docs/b.md",
|
|
84
|
-
"precondition": {"type": "content_sha256", "content_sha256": "<sha from last read>"}
|
|
85
|
-
}'
|
|
86
|
-
|
|
87
|
-
# Delete
|
|
88
|
-
curl -sS -X DELETE "$BASE/v1/repositories/{repository_id}/files/content" -H "$AUTH" \
|
|
89
|
-
-H "Content-Type: application/json" -d '{"path": "docs/b.md"}'
|
|
90
|
-
# → {"success": true, "commit_sha": "..."}
|
|
48
|
+
git -C "$MEMORY_DIR/../<repo-name>" log --oneline -- <path>
|
|
91
49
|
```
|
|
92
50
|
|
|
93
|
-
|
|
51
|
+
## Managing Repositories (create / attach / detach)
|
|
52
|
+
|
|
53
|
+
Use the `letta shared-memory` subcommand. It uses your harness auth (works even when `LETTA_API_KEY` is not in the shell env) and inherits the agent id from `AGENT_ID`, so `--agent` is only needed when targeting another agent.
|
|
94
54
|
|
|
95
55
|
```bash
|
|
96
|
-
# List
|
|
97
|
-
|
|
98
|
-
# → {"commits": [{"sha": "...", "message": "...", "timestamp": "...", "author_name": ...}]}
|
|
56
|
+
# List org repositories (marks which are attached to you)
|
|
57
|
+
letta shared-memory list
|
|
99
58
|
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
```
|
|
59
|
+
# Create a repository
|
|
60
|
+
letta shared-memory create --name shared-notes
|
|
103
61
|
|
|
104
|
-
|
|
62
|
+
# Attach to yourself: attaches via the API, clones the local mount at
|
|
63
|
+
# $MEMORY_DIR/../shared-notes, and recompiles the system prompt projection
|
|
64
|
+
letta shared-memory attach shared-notes
|
|
105
65
|
|
|
106
|
-
|
|
66
|
+
# Attach to another agent (its mount materializes in that agent's environments)
|
|
67
|
+
letta shared-memory attach shared-notes --agent agent-...
|
|
107
68
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
curl -sS "$BASE/v1/agents/{agent_id}/repositories" -H "$AUTH"
|
|
69
|
+
# Detach (leaves the local mount directory in place)
|
|
70
|
+
letta shared-memory detach shared-notes
|
|
111
71
|
|
|
112
|
-
#
|
|
113
|
-
|
|
114
|
-
|
|
72
|
+
# Repair/refresh mounts: clone or pull every attached repository. Use this when
|
|
73
|
+
# the system prompt references a repository that is missing on disk (e.g. after
|
|
74
|
+
# it was attached from another surface while this session was running).
|
|
75
|
+
letta shared-memory sync
|
|
115
76
|
|
|
116
|
-
#
|
|
117
|
-
|
|
77
|
+
# Commit history via the API (works even without a local mount)
|
|
78
|
+
letta shared-memory history shared-notes --path docs/plan.md
|
|
118
79
|
```
|
|
119
80
|
|
|
120
|
-
|
|
81
|
+
## Troubleshooting
|
|
82
|
+
|
|
83
|
+
- **Prompt lists a repository but `$MEMORY_DIR/../<name>` is missing** — the repository was attached without materializing the mount. Run `letta shared-memory sync`.
|
|
84
|
+
- **`sync` reports "mount path already exists and is not a git repository"** — a plain directory (usually created by hand before the mount existed) is occupying the mount path. Inspect it, salvage anything worth keeping, move or delete it, then re-run `letta shared-memory sync`.
|
|
85
|
+
- **Never hand-clone the repository to another location (e.g. /tmp) to work around a broken mount** — fix the mount with `letta shared-memory sync` so every session and other agents see the same checkout.
|
|
86
|
+
- **Permission denied under another agent's directory** — shared repositories mount per-agent. Only your own mount (under your agent directory) is accessible; another agent's mount of the same repository is walled off by the cross-agent guard. Run `letta shared-memory sync` to get your own mount.
|
|
87
|
+
- **Push rejected (non-fast-forward)** — another agent pushed first: `git pull --rebase`, resolve any conflicts, push again.
|
|
121
88
|
|
|
122
89
|
## Notes and Limits
|
|
123
90
|
|
|
124
|
-
- Shared memory files are **text** content; binary files are not supported via the files API.
|
|
125
|
-
- Attached shared memory is not scoped to you — another agent may edit the same files at any time. Use the `content_sha256` precondition on updates when multiple agents may write the same file; on failure, re-read and retry.
|
|
126
91
|
- Shared memory is not part of your system prompt. Writing to it does not change your in-context memory — for that, edit your memory blocks or MemFS files.
|
|
127
|
-
-
|
|
92
|
+
- Attaching is asynchronous on the server; `letta shared-memory attach` waits for the attachment to be visible before cloning.
|
|
93
|
+
- SDK/API equivalent for programmatic callers: `@letta-ai/letta-agent-sdk` exposes these operations as `client.repositories` (with `files` and `versions` helpers), and shared memory can be attached for a session's lifetime via `resources: [{ type: "repository", repositoryId }]` on cloud sessions. The REST resource is `/v1/repositories`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scheduling-tasks
|
|
3
|
-
description: Schedules reminders and recurring tasks via the letta cron CLI. Use when the user asks to be reminded of something, wants periodic
|
|
3
|
+
description: Schedules reminders and recurring tasks via the letta cron CLI. Use when the user asks to be reminded of something, wants periodic work or check-ins, or needs to list, inspect, replace, or cancel scheduled tasks.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Scheduling Tasks
|
|
@@ -14,28 +14,24 @@ This skill lets you create, list, and manage scheduled tasks using the `letta cr
|
|
|
14
14
|
- User wants a one-shot delayed message ("in 30 minutes, check on X")
|
|
15
15
|
- User wants to see or cancel existing scheduled tasks
|
|
16
16
|
|
|
17
|
-
## Where Schedules Run
|
|
17
|
+
## Where Schedules Run — Omit the Flags
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**Default guidance: omit `--runner` and `--computer`.** The CLI places the schedule so the work keeps running on the computer where it was created. Don't move scheduled work to a different computer than the active conversation without a reason: two computers working the same conversation can conflict.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- **`local`**: a task local to the current computer (`~/.letta/crons.json`), executed by the Letta session running there. It only fires while a session is running on that computer, and it dies with that computer's local state.
|
|
21
|
+
Pass a flag only when you have a requirement the default can't infer:
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
- **`--runner cloud`** — the schedule must fire no matter which computers are online; execute in the agent's cloud sandbox.
|
|
24
|
+
- **`--computer <deviceId>`** — the work needs a specific connected computer (its filesystem, services, or credentials). Get the deviceId from `letta environments list`. If that computer is offline at fire time, execution falls back to the cloud sandbox.
|
|
25
|
+
- **`--runner local`** — the work must only ever run on the current computer, even if that means missing fires while no session is running here.
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
The CLI reports its placement in the command output. If it warns that the schedule is local (this happens when the cloud scheduler cannot reach the current computer), the schedule only fires while a Letta session is running here — read the warning and decide whether that's acceptable.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
letta cron add ... --computer <deviceId>
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The deviceId comes from `letta environments list`. The computer must be connected to your Letta account (run `letta server` on it, or enable remote access in the desktop app). The schedule stays durable in the cloud; if the computer is offline when it fires, execution falls back to the agent's cloud sandbox. Use `--runner local` (run on the target computer itself) only when that sandbox fallback is unacceptable — a local task never runs anywhere but its own computer.
|
|
29
|
+
### Fast Follow-ups vs Recurring Jobs
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
Two patterns cover most schedules:
|
|
35
32
|
|
|
36
|
-
-
|
|
37
|
-
- Recurring
|
|
38
|
-
- If creating a Cloud schedule fails, no schedule is created — there is no silent fallback to local storage. Retry, or pass `--runner local` deliberately.
|
|
33
|
+
- **Fast follow-ups** ("check on the PR in 5m"): the default is right — same computer as the active conversation. If the session dies before it fires, the follow-up usually died with the task anyway.
|
|
34
|
+
- **Recurring jobs** ("every Monday 11am, start the lunch order"): prefer durability. If the CLI warned that a recurring schedule is local, that's usually wrong for the user's intent — recreate it with `--runner cloud`, or `--computer` if the job needs a specific always-on computer. Also consider whether the job should post into a dedicated conversation rather than this one (continuity in one thread vs a fresh context per run).
|
|
39
35
|
|
|
40
36
|
## CLI Usage
|
|
41
37
|
|
|
@@ -59,7 +55,7 @@ letta cron add --name <short-name> --description <text> --prompt <text> <schedul
|
|
|
59
55
|
|
|
60
56
|
| Flag | Type | Example |
|
|
61
57
|
|------|------|---------|
|
|
62
|
-
| `--every <interval>` | Recurring | `5m`, `2h`, `1d` |
|
|
58
|
+
| `--every <interval>` | Recurring (cron shorthand) | `5m`, `2h`, `1d` |
|
|
63
59
|
| `--at <time>` | One-shot | `"3:00pm"`, `"in 45m"` |
|
|
64
60
|
| `--cron <expr>` | Raw cron (recurring) | `"0 9 * * 1-5"` |
|
|
65
61
|
|
|
@@ -69,8 +65,9 @@ letta cron add --name <short-name> --description <text> --prompt <text> <schedul
|
|
|
69
65
|
|------|-------------|
|
|
70
66
|
| `--agent <id>` | Agent ID (defaults to `LETTA_AGENT_ID` from the current shell/session) |
|
|
71
67
|
| `--conversation <id>` | Conversation ID (defaults to `LETTA_CONVERSATION_ID` from the current shell/session, otherwise `"default"`) |
|
|
72
|
-
| `--runner <runner>` | `cloud` or `local` — see "Where Schedules Run" above
|
|
73
|
-
| `--computer <id>` |
|
|
68
|
+
| `--runner <runner>` | `cloud` or `local` — normally omit; see "Where Schedules Run" above |
|
|
69
|
+
| `--computer <id>` | Execute on a specific connected computer — normally omit |
|
|
70
|
+
| `--once` | Mark `--at` as one-shot (already the default for `--at`) |
|
|
74
71
|
|
|
75
72
|
### Listing Tasks
|
|
76
73
|
|
|
@@ -78,14 +75,24 @@ letta cron add --name <short-name> --description <text> --prompt <text> <schedul
|
|
|
78
75
|
letta cron list
|
|
79
76
|
```
|
|
80
77
|
|
|
81
|
-
Optional filters: `--agent <id>`, `--conversation <id
|
|
78
|
+
Optional filters: `--agent <id>`, `--conversation <id>`, `--runner local|cloud`
|
|
82
79
|
|
|
83
80
|
### Getting a Single Task
|
|
84
81
|
|
|
82
|
+
`get` accepts an ID or name:
|
|
83
|
+
|
|
85
84
|
```bash
|
|
86
|
-
letta cron get <
|
|
85
|
+
letta cron get <id-or-name> [--runner local|cloud] [--agent <id>]
|
|
87
86
|
```
|
|
88
87
|
|
|
88
|
+
### Reading Run History
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
letta cron runs --id <task-id> [--limit <n>] [--runner local|cloud] [--agent <id>]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For local run history, `--run-id <id>` selects one run. Cloud history ignores that flag.
|
|
95
|
+
|
|
89
96
|
### Binding a Task to the Right Conversation
|
|
90
97
|
|
|
91
98
|
If exact routing matters, pass both `--agent` and `--conversation` explicitly.
|
|
@@ -110,58 +117,60 @@ Then verify the binding explicitly:
|
|
|
110
117
|
letta cron list --agent "$AGENT_ID" --conversation "$CONVERSATION_ID"
|
|
111
118
|
```
|
|
112
119
|
|
|
113
|
-
### Deleting Tasks
|
|
120
|
+
### Deleting or Replacing Tasks
|
|
121
|
+
|
|
122
|
+
`delete` accepts an ID or name; `remove` is an alias.
|
|
114
123
|
|
|
115
124
|
```bash
|
|
116
125
|
# Delete a specific task
|
|
117
|
-
letta cron delete <
|
|
126
|
+
letta cron delete <id-or-name> [--runner local|cloud] [--agent <id>]
|
|
118
127
|
|
|
119
|
-
# Delete all tasks for
|
|
120
|
-
letta cron delete --all
|
|
128
|
+
# Delete all tasks for one agent
|
|
129
|
+
letta cron delete --all --agent "$AGENT_ID"
|
|
121
130
|
```
|
|
122
131
|
|
|
123
|
-
|
|
132
|
+
In-place editing is not available. To change a schedule, create and verify the replacement before deleting the old one.
|
|
124
133
|
|
|
125
|
-
|
|
134
|
+
## Timezones — Convert Before Writing `--cron`
|
|
126
135
|
|
|
127
|
-
|
|
128
|
-
letta cron add \
|
|
129
|
-
--name "dog-walk-reminder" \
|
|
130
|
-
--description "Daily morning reminder to walk the dog" \
|
|
131
|
-
--prompt "Hey! It's 9am — time to walk the dog." \
|
|
132
|
-
--every 1d
|
|
133
|
-
```
|
|
136
|
+
Cloud-schedule recurring expressions (both `--cron` and the expression `--every` compiles to) are interpreted in **UTC**. Users say times in their local timezone, so convert before writing the expression: a user in PDT asking for "9am daily" needs `--cron "0 16 * * *"` (9am PDT = 16:00 UTC; 17:00 during PST). State the conversion in your reply so the user can catch a wrong assumption. Local-runner tasks use the computer's local timezone — no conversion. `--at` stores one absolute timestamp parsed in the current process timezone, so it needs no conversion either.
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
## Examples
|
|
139
|
+
|
|
140
|
+
### "Remind me every morning at 9am to walk the dog" (user in UTC−7)
|
|
136
141
|
|
|
137
142
|
```bash
|
|
138
143
|
letta cron add \
|
|
139
144
|
--name "dog-walk-reminder" \
|
|
140
|
-
--description "Daily 9am reminder to walk the dog" \
|
|
145
|
+
--description "Daily 9am (America/Los_Angeles) reminder to walk the dog" \
|
|
141
146
|
--prompt "Hey! It's 9am — time to walk the dog." \
|
|
142
|
-
--cron "0
|
|
147
|
+
--cron "0 16 * * *"
|
|
143
148
|
```
|
|
144
149
|
|
|
150
|
+
Note: `--every 1d` fires daily at midnight (UTC on a Cloud schedule), so use `--cron` for a specific time of day, converting the user's local time to UTC first.
|
|
151
|
+
|
|
145
152
|
### "Check on the deploy in 30 minutes"
|
|
146
153
|
|
|
147
154
|
```bash
|
|
148
155
|
letta cron add \
|
|
149
156
|
--name "deploy-check" \
|
|
150
157
|
--description "One-time check on deployment status" \
|
|
151
|
-
--prompt "
|
|
158
|
+
--prompt "Check the deployment status and report the result here." \
|
|
152
159
|
--at "in 30m"
|
|
153
160
|
```
|
|
154
161
|
|
|
155
|
-
### "Every weekday at 5pm, remind me to submit my timesheet"
|
|
162
|
+
### "Every weekday at 5pm, remind me to submit my timesheet" (user in UTC−7)
|
|
156
163
|
|
|
157
164
|
```bash
|
|
158
165
|
letta cron add \
|
|
159
166
|
--name "timesheet-reminder" \
|
|
160
|
-
--description "Weekday 5pm timesheet reminder" \
|
|
167
|
+
--description "Weekday 5pm (America/Los_Angeles) timesheet reminder" \
|
|
161
168
|
--prompt "Friendly reminder: don't forget to submit your timesheet before EOD!" \
|
|
162
|
-
--cron "0
|
|
169
|
+
--cron "0 0 * * 2-6"
|
|
163
170
|
```
|
|
164
171
|
|
|
172
|
+
Note the day shift: 5pm UTC−7 is midnight UTC the *next* day, so weekdays Mon–Fri become `2-6`. Always re-derive both the hour and the day fields after converting.
|
|
173
|
+
|
|
165
174
|
### "What reminders do I have?"
|
|
166
175
|
|
|
167
176
|
```bash
|
|
@@ -176,12 +185,8 @@ letta cron list --agent "$AGENT_ID" --conversation "$CONVERSATION_ID"
|
|
|
176
185
|
|
|
177
186
|
### "Cancel the dog walk reminder"
|
|
178
187
|
|
|
179
|
-
First list to find the task ID, then delete:
|
|
180
|
-
|
|
181
188
|
```bash
|
|
182
|
-
letta cron
|
|
183
|
-
# Find the task ID from the output, then:
|
|
184
|
-
letta cron delete <task-id>
|
|
189
|
+
letta cron delete dog-walk-reminder
|
|
185
190
|
```
|
|
186
191
|
|
|
187
192
|
## Writing Good Prompts
|
|
@@ -198,15 +203,14 @@ Include context about what the user originally asked for, so you can give a help
|
|
|
198
203
|
- **Minimum granularity**: 1 minute. Intervals under 60 seconds are rounded up.
|
|
199
204
|
- **Recurring tasks**: No longer auto-expire. They remain active until explicitly cancelled.
|
|
200
205
|
- **One-shot cleanup (local runner)**: One-shot local tasks are garbage-collected 24 hours after firing.
|
|
201
|
-
- **Timezone**: Local-runner tasks use the user's local timezone. Cloud-runner recurring `--cron` expressions are currently interpreted in UTC.
|
|
202
206
|
- **Default binding precedence**: `letta cron add` uses `--agent` / `--conversation` first, then falls back to `LETTA_AGENT_ID` / `LETTA_CONVERSATION_ID`, then finally uses `"default"` for the conversation if no env var is present.
|
|
203
|
-
- **Local scheduler requirement**: Local
|
|
207
|
+
- **Local scheduler requirement**: Local schedules only fire while a Letta session is running on their computer; fires while no session runs are marked as missed. Cloud schedules fire from the cloud regardless.
|
|
204
208
|
- **`--at` for specific times**: `--at "3:00pm"` schedules a one-shot. If the time has already passed today, it schedules for tomorrow.
|
|
205
|
-
-
|
|
209
|
+
- **Cloud schedule creation failures are loud**: if creating a cloud schedule fails, no schedule is created — a failed create never silently becomes a local schedule. (The local placement for computers the cloud scheduler can't reach is decided before creation and reported in the output.)
|
|
206
210
|
|
|
207
211
|
## Cron Expression Reference
|
|
208
212
|
|
|
209
|
-
For `--cron`, use
|
|
213
|
+
For `--cron`, use numeric 5-field cron syntax (named days/months, seconds, `?`, `L`, and `#` are not supported):
|
|
210
214
|
|
|
211
215
|
```
|
|
212
216
|
┌───────────── minute (0-59)
|
|
@@ -218,9 +222,9 @@ For `--cron`, use standard 5-field cron syntax:
|
|
|
218
222
|
* * * * *
|
|
219
223
|
```
|
|
220
224
|
|
|
221
|
-
Common patterns:
|
|
225
|
+
Common patterns (UTC on Cloud schedules):
|
|
222
226
|
- `*/5 * * * *` — every 5 minutes
|
|
223
227
|
- `0 */2 * * *` — every 2 hours
|
|
224
|
-
- `0 9 * * *` — daily at
|
|
225
|
-
- `0 9 * * 1-5` — weekdays at
|
|
226
|
-
- `30 8 1 * *` — 8:
|
|
228
|
+
- `0 9 * * *` — daily at 9:00 UTC
|
|
229
|
+
- `0 9 * * 1-5` — weekdays at 9:00 UTC
|
|
230
|
+
- `30 8 1 * *` — 8:30 UTC on the 1st of each month
|