@letta-ai/letta-code 0.34.16 → 0.34.18
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 +14 -5
- package/dist/agent-presets.js +5 -1
- package/dist/agent-presets.js.map +2 -2
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-oauth.js +30 -28
- package/dist/mcp-oauth.js.map +4 -4
- package/dist/types/agent/client-skills.d.ts.map +1 -1
- package/dist/types/agent/message.d.ts.map +1 -1
- package/dist/types/agent/model-handles.d.ts.map +1 -1
- package/dist/types/agent/preloaded-skills.d.ts +4 -0
- package/dist/types/agent/preloaded-skills.d.ts.map +1 -0
- package/dist/types/agent/skills.d.ts.map +1 -1
- package/dist/types/agent/subagents/child-send-tracking.d.ts.map +1 -1
- package/dist/types/agent/subagents/index.d.ts.map +1 -1
- package/dist/types/agent/subagents/manager.d.ts.map +1 -1
- package/dist/types/agent/subagents/remote-turn-wait.d.ts.map +1 -1
- package/dist/types/agent/subagents/subagent-stream.d.ts.map +1 -1
- package/dist/types/agent/turn-recovery-policy.d.ts +1 -1
- package/dist/types/agent/turn-recovery-policy.d.ts.map +1 -1
- package/dist/types/auth/oauth.d.ts +8 -1
- package/dist/types/auth/oauth.d.ts.map +1 -1
- package/dist/types/backend/api/conversation-enqueue.d.ts +4 -1
- package/dist/types/backend/api/conversation-enqueue.d.ts.map +1 -1
- package/dist/types/backend/dev/fake-headless-backend.d.ts +9 -2
- package/dist/types/backend/dev/fake-headless-backend.d.ts.map +1 -1
- package/dist/types/backend/local/compaction.d.ts +5 -0
- package/dist/types/backend/local/compaction.d.ts.map +1 -1
- package/dist/types/backend/local/local-backend.d.ts.map +1 -1
- package/dist/types/headless-listener-launch.d.ts +5 -3
- package/dist/types/headless-listener-launch.d.ts.map +1 -1
- package/dist/types/headless-super-run-wait.d.ts +1 -1
- package/dist/types/headless-super-run-wait.d.ts.map +1 -1
- package/dist/types/mcp-oauth-callback.d.ts +5 -1
- package/dist/types/mcp-oauth-callback.d.ts.map +1 -1
- package/dist/types/mcp-oauth.d.ts.map +1 -1
- package/dist/types/tools/impl/code-mode.d.ts +23 -0
- package/dist/types/tools/impl/code-mode.d.ts.map +1 -0
- 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/remote-external-coding-agent.d.ts +1 -0
- package/dist/types/tools/impl/remote-external-coding-agent.d.ts.map +1 -1
- package/dist/types/tools/impl/task-stop.d.ts.map +1 -1
- package/dist/types/tools/impl/workflow.d.ts +5 -0
- package/dist/types/tools/impl/workflow.d.ts.map +1 -1
- package/dist/types/tools/manager.d.ts.map +1 -1
- package/dist/types/tools/script-tool-scope.d.ts +19 -0
- package/dist/types/tools/script-tool-scope.d.ts.map +1 -0
- package/dist/types/tools/tool-definitions.d.ts +1 -0
- package/dist/types/tools/tool-definitions.d.ts.map +1 -1
- package/dist/types/tools/toolset-catalog.d.ts +1 -1
- package/dist/types/tools/toolset-catalog.d.ts.map +1 -1
- package/dist/types/tools/workflow/sdk-spawner.d.ts.map +1 -1
- package/dist/types/tools/workflow/types.d.ts +2 -0
- package/dist/types/tools/workflow/types.d.ts.map +1 -1
- package/dist/types/tools/workflow/workflow-engine.d.ts +2 -0
- package/dist/types/tools/workflow/workflow-engine.d.ts.map +1 -1
- package/letta.js +13825 -13502
- package/npm-shrinkwrap.json +86 -86
- package/package.json +2 -2
- package/scripts/source-file-size-baseline.json +3 -3
- package/skills/creating-skills/SKILL.md +14 -13
- package/skills/maintaining-core-memory/SKILL.md +101 -0
- package/skills/maintaining-deferred-memory/SKILL.md +84 -0
- package/skills/music-generation/LICENSE +21 -0
- package/skills/music-generation/SKILL.md +164 -0
- package/skills/speech-generation/SKILL.md +15 -36
- package/skills/workflow-authoring/SKILL.md +3 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maintaining-deferred-memory
|
|
3
|
+
description: Maintains deferred memory, which stores accumulated knowledge, analysis, and observations made by the agent over time. Use when saving knowledge (e.g. about a person, project, repository, system, or event). Do NOT use for managing skills, prompts, or for saving information that is already automatically stored in the message history.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Deferred memory contains the agent's knowledge. Use deferred memory for understanding of a subject that matters only when that subject comes up. If the agent needs it on most turns, it is core memory: use the `maintaining-core-memory` skill. If it is a procedure with a trigger, use the `creating-skills` skill.
|
|
7
|
+
|
|
8
|
+
Deferred memory should NOT be used to store:
|
|
9
|
+
- Information that can be accessed by querying the message history (recall memory). For example, logs of specific interactions can simply be looked up in past messages. Reserve deferred memory to store knowledge that is actually *derived* from experience, or to organize knowledge in a way that optimizes recalling the right information at the right time through progressive disclosure.
|
|
10
|
+
- Justifications or reasons for updating memory. These belong in the git commit history of MemFS.
|
|
11
|
+
|
|
12
|
+
## Check the limits first
|
|
13
|
+
|
|
14
|
+
Read `$MEMORY_DIR/.memfs.config.json` if it exists. The memory repository's pre-commit hook enforces it:
|
|
15
|
+
|
|
16
|
+
- `maxDepth` limits how many directories can sit between the memory root and a file (default 2). `persona.md` is depth 0, `projects/MEMORY.md` is depth 1, and `projects/acme/notes.md` is depth 2. `skills/` is exempt.
|
|
17
|
+
- `maxFileCharacters` caps each memory file, frontmatter included (default 20,000 characters). `fileCharacterLimits` overrides it per glob; the first match wins and `null` removes the cap.
|
|
18
|
+
- `readOnlyFiles` lists globs whose files cannot change. Do not edit them.
|
|
19
|
+
|
|
20
|
+
When the config file is absent, the defaults apply. When content does not fit, split it into more files or flatten the structure; change the config only when the user asks.
|
|
21
|
+
|
|
22
|
+
## Layout
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
$MEMORY_DIR/
|
|
26
|
+
├── MEMORY.md # root index (core memory)
|
|
27
|
+
└── projects/
|
|
28
|
+
├── MEMORY.md # index for projects/
|
|
29
|
+
├── acme.md
|
|
30
|
+
└── acme/
|
|
31
|
+
├── MEMORY.md # index for projects/acme/
|
|
32
|
+
└── incidents.md
|
|
33
|
+
```
|
|
34
|
+
- The top-level `MEMORY.md` is always in context, so it must tell the agent what each subdirectory contains and when to open it. Without that entry the directory is never read.
|
|
35
|
+
- `skills/` is reserved for skills and is never deferred memory.
|
|
36
|
+
- A directory is memory only when it has its own `MEMORY.md`. The agent will not discover a directory without one, and neither will the files in it.
|
|
37
|
+
- Every `MEMORY.md` has no frontmatter.
|
|
38
|
+
- Every other Markdown file starts with frontmatter containing exactly two fields:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
---
|
|
42
|
+
name: acme
|
|
43
|
+
description: How the Acme integration works, why it fails, and what to do about it.
|
|
44
|
+
---
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- `description` says what the file is about. The agent sees it when it lists the directory, so make it specific enough to decide whether to open the file.
|
|
48
|
+
- Name files and directories after their subject, not after a date or session. Group related subjects under one directory instead of creating many top-level directories.
|
|
49
|
+
|
|
50
|
+
## Write the indexes
|
|
51
|
+
|
|
52
|
+
Discovery runs through the `MEMORY.md` chain, one level at a time:
|
|
53
|
+
|
|
54
|
+
- The system prompt lists each top-level memory directory only by path. Add a line to root `MEMORY.md` saying when to open the directory, in the words a future request would use. When a deeper file's topic would not be guessable from that line, name the file there too.
|
|
55
|
+
- When the agent opens a directory, it sees that directory's `MEMORY.md`, then each file's `description` and each subdirectory's index summary (the first prose paragraph of its `MEMORY.md`). Start every `MEMORY.md` with that summary paragraph.
|
|
56
|
+
- A directory listing shows at most 10 entries, most recently edited first, so stable files fall out of it. Link every file that matters from its `MEMORY.md` rather than relying on the listing.
|
|
57
|
+
- Use relative Markdown links from the memory root, such as `[Acme](projects/acme.md)`.
|
|
58
|
+
|
|
59
|
+
After adding or moving a file, trace the path a future request would take from root `MEMORY.md` to the file. If any step depends on knowing the file already exists, fix the index.
|
|
60
|
+
|
|
61
|
+
## Design for progressive disclosure
|
|
62
|
+
|
|
63
|
+
Each level should give the agent enough to decide whether to go deeper, and nothing it would have to read past to decide.
|
|
64
|
+
|
|
65
|
+
- Put frequently needed material shallow and rarely needed detail deeper. Keep related material in one directory so it loads together.
|
|
66
|
+
- A small topic, where most of the content is useful whenever the subject comes up, belongs entirely in its directory's `MEMORY.md`. Splitting it adds reads without saving context.
|
|
67
|
+
- For a large topic, `MEMORY.md` holds only what the agent needs every time it opens the directory, plus a map: what each deeper file or subdirectory covers and when it is worth opening. The map should also tell the agent when it can stop.
|
|
68
|
+
- A `description` states what the file is about, not when to use it; when-to-open belongs in the parent's link. If you can write a "use when the user wants to…" trigger, the content is a procedure and belongs in a skill.
|
|
69
|
+
- Make each statement stand alone. Name the subject instead of writing "it" or "the repo", because the agent may read only part of a file.
|
|
70
|
+
- Aim for fewer than 10 entries per directory so the listing stays complete. At the `maxDepth` limit, use clearly scoped sibling files linked from `MEMORY.md` rather than nesting further.
|
|
71
|
+
|
|
72
|
+
## Write analysis, not logs
|
|
73
|
+
|
|
74
|
+
Recall already returns what happened. A deferred memory file is worth keeping only when it holds what recall cannot: the agent's own synthesis of a subject, built across many events and refined as understanding improves.
|
|
75
|
+
|
|
76
|
+
- Before writing, ask whether searching message history would give a future agent the same thing. If it would, do not write the file.
|
|
77
|
+
- Write the current understanding: how the subject works, the patterns across events, why things failed or succeeded, what to do about it, and the open questions.
|
|
78
|
+
- Revise the file in place when new evidence arrives. Fold the new event into the analysis; never append a dated entry, a quote, or an incident narrative.
|
|
79
|
+
- When the file you are updating is already a log, convert it: write the analysis the entries support and delete the entries. Keeping them under an "incident history" heading leaves the log in place; git and recall already hold it.
|
|
80
|
+
- When a raw event matters, point to it with terms that will find it in recall rather than copying it.
|
|
81
|
+
- Keep one home per subject. Update the existing file instead of adding a near-duplicate, and replace stale conclusions where they live.
|
|
82
|
+
- Leave out content the agent can cheaply rederive from the source of truth: file contents, command lists, and current status. Link to the owning source instead.
|
|
83
|
+
- Never store secrets. Reference them by name, such as `$SECRET_NAME`.
|
|
84
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ElevenLabs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: music-generation
|
|
3
|
+
description: Generate music using ElevenLabs Music through Letta. Use when creating instrumental tracks, songs with lyrics, background music, jingles, theme songs, or any AI-generated music composition. Supports prompt-based generation and composition plans for section-by-section control.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ElevenLabs Music Generation (via Letta)
|
|
8
|
+
|
|
9
|
+
Generate music from text prompts: instrumental tracks, songs with lyrics, and fine-grained control via composition plans. Examples use `music_v2_5`, the most advanced ElevenLabs music model and the endpoint's default.
|
|
10
|
+
|
|
11
|
+
This skill is adapted from ElevenLabs' `music` skill
|
|
12
|
+
([elevenlabs/skills](https://github.com/elevenlabs/skills), MIT; see `LICENSE`).
|
|
13
|
+
Instead of calling ElevenLabs with your own key, you call Letta's hosted endpoint
|
|
14
|
+
`POST /v1/audio/music` (or `POST /v1/audio/music/stream`). It forwards the
|
|
15
|
+
request to ElevenLabs with Letta's key and charges the organization's Letta
|
|
16
|
+
credits, so you do not need an ElevenLabs API key. The request and response are
|
|
17
|
+
the same as ElevenLabs "Compose music": a JSON body with the same field names,
|
|
18
|
+
`output_format` as a query parameter, and the audio file as the response body.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
base_url="${LETTA_BASE_URL%/}"
|
|
24
|
+
|
|
25
|
+
curl -sS -X POST "$base_url/v1/audio/music/stream?output_format=mp3_48000_192" \
|
|
26
|
+
-H "Authorization: Bearer $LETTA_API_KEY" \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d '{"prompt":"A chill lo-fi hip hop beat with jazzy piano chords","music_length_ms":30000,"model_id":"music_v2_5"}' \
|
|
29
|
+
--output output.mp3 \
|
|
30
|
+
--write-out '%{http_code} %{content_type}\n'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
A `200` with an `audio/...` content type means `output.mp3` is the song. Any
|
|
34
|
+
other status means `output.mp3` holds a JSON error with a `message` instead;
|
|
35
|
+
read it (see "Error Handling") and do not share the file.
|
|
36
|
+
|
|
37
|
+
Use the runtime-provided `LETTA_BASE_URL` and `LETTA_API_KEY` together. Build
|
|
38
|
+
URLs relative to `${LETTA_BASE_URL%/}` and do not hardcode
|
|
39
|
+
`https://api.letta.com`. If either variable is missing, the user needs to
|
|
40
|
+
authenticate with Letta Cloud; do not ask for an ElevenLabs key.
|
|
41
|
+
|
|
42
|
+
Generation takes a while (roughly 10-30 seconds per minute of music). Prefer
|
|
43
|
+
`/v1/audio/music/stream`: it sends audio as it is generated, so long songs do
|
|
44
|
+
not sit on an idle connection. `/v1/audio/music` takes the same request and
|
|
45
|
+
returns the same file, but may send nothing until the whole song is done, so
|
|
46
|
+
use it only for short songs. Do not set a short client timeout either way.
|
|
47
|
+
|
|
48
|
+
Share the saved file the way your current surface supports: attach or upload it
|
|
49
|
+
to the conversation or channel you are replying in. Keep credit amounts out of
|
|
50
|
+
replies unless the user asks about cost.
|
|
51
|
+
|
|
52
|
+
## Length
|
|
53
|
+
|
|
54
|
+
- A song is 3 seconds to 10 minutes (600,000 ms).
|
|
55
|
+
- With `prompt`, `music_length_ms` is optional. Leave it out to let the model
|
|
56
|
+
choose a length that suits the prompt.
|
|
57
|
+
- With `composition_plan`, the length is the sum of the chunk or section
|
|
58
|
+
`duration_ms` values; do not also send `music_length_ms`.
|
|
59
|
+
- Credits are charged for the length of the audio actually returned, at
|
|
60
|
+
ElevenLabs' per-minute price. Before generating, the organization needs
|
|
61
|
+
enough credits for the longest song the request allows: `music_length_ms`,
|
|
62
|
+
the plan total, or 10 minutes when a prompt sets no length. Setting
|
|
63
|
+
`music_length_ms` lowers that requirement.
|
|
64
|
+
|
|
65
|
+
## Models
|
|
66
|
+
|
|
67
|
+
| Model ID | Best For |
|
|
68
|
+
|----------|----------|
|
|
69
|
+
| `music_v2_5` | **Default.** Most advanced: best audio quality and prompt adherence. Chunk-based composition plans. |
|
|
70
|
+
| `music_v2` | Previous generation. Chunk-based composition plans. |
|
|
71
|
+
| `music_v1` | Oldest. Section-based composition plans. Use only when explicitly requested. |
|
|
72
|
+
|
|
73
|
+
## Prompting
|
|
74
|
+
|
|
75
|
+
Describe the music the way a producer would brief a session:
|
|
76
|
+
|
|
77
|
+
- Genre and mood: "melancholic indie folk", "triumphant orchestral trailer".
|
|
78
|
+
- Instrumentation and vocals: "fingerpicked acoustic guitar, soft female vocals".
|
|
79
|
+
- Tempo and key when they matter: "90 BPM", "D minor".
|
|
80
|
+
- Structure and energy: "starts sparse, builds into a big chorus".
|
|
81
|
+
- Lyrics: put them in the prompt for short songs, or use a composition plan
|
|
82
|
+
to control which lines land in which section.
|
|
83
|
+
- Set `force_instrumental: true` to guarantee no vocals (prompt mode only).
|
|
84
|
+
|
|
85
|
+
## Composition Plans
|
|
86
|
+
|
|
87
|
+
`music_v2_5` composition plans are an ordered list of `chunks`. Each chunk specifies its own
|
|
88
|
+
`text` (section label, lyrics, inline cues), `duration_ms`, `positive_styles`, `negative_styles`,
|
|
89
|
+
and `context_adherence` (`low`, `medium`, or `high`, default `high`). Up to 30 chunks per plan,
|
|
90
|
+
each 3,000–120,000 ms. Each chunk's `text` supports up to 6,132 characters, with up to 30 lines
|
|
91
|
+
of 200 characters each. Send the plan instead of `prompt` and `music_length_ms`:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"model_id": "music_v2_5",
|
|
96
|
+
"composition_plan": {
|
|
97
|
+
"chunks": [
|
|
98
|
+
{
|
|
99
|
+
"text": "[Verse]\nWalking down an empty street",
|
|
100
|
+
"duration_ms": 15000,
|
|
101
|
+
"positive_styles": ["pop", "upbeat", "female vocals", "acoustic guitar", "120 BPM", "polished production"],
|
|
102
|
+
"negative_styles": ["dark", "slow"],
|
|
103
|
+
"context_adherence": "high"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"text": "[Chorus]\nThis is my moment",
|
|
107
|
+
"duration_ms": 15000,
|
|
108
|
+
"positive_styles": ["powerful vocals", "full band"],
|
|
109
|
+
"negative_styles": [],
|
|
110
|
+
"context_adherence": "high"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- Put broader characteristics (genre, instrumentation, vocal style) in `positive_styles`, not in
|
|
118
|
+
`text`. The first chunk's styles set the overall tone — include 6–7 styles there.
|
|
119
|
+
- Use later chunks' styles for progression: "bass joins in", "building intensity", "drums softening".
|
|
120
|
+
- Inline cues in curly braces add moments inside a chunk: `{guitar solo}`, `{vinyl crackle}`.
|
|
121
|
+
- Lower `context_adherence` lets a chunk depart from its neighbors, for a bridge or a key change.
|
|
122
|
+
- `seed` works with composition plans (not with `prompt`) to make results more repeatable.
|
|
123
|
+
|
|
124
|
+
For `music_v1`, plans use `positive_global_styles`, `negative_global_styles`, and `sections`
|
|
125
|
+
(each with `section_name`, `positive_local_styles`, `negative_local_styles`, `duration_ms`, and
|
|
126
|
+
`lines`), and `respect_sections_durations: false` lets the model adjust section lengths.
|
|
127
|
+
|
|
128
|
+
Inpainting and audio references (`song_id` chunks, `conditioning_ref`, `source_from`) are not
|
|
129
|
+
available through this endpoint and return 400.
|
|
130
|
+
|
|
131
|
+
## Output Formats
|
|
132
|
+
|
|
133
|
+
Pass `output_format` as a query parameter, not in the body. The default, `auto`,
|
|
134
|
+
gives `mp3_48000_192` for `music_v2` and later (`mp3_44100_128` for `music_v1`).
|
|
135
|
+
Name the file to match the format.
|
|
136
|
+
|
|
137
|
+
| Format | Description |
|
|
138
|
+
|--------|-------------|
|
|
139
|
+
| `mp3_48000_192` | MP3 48kHz 192kbps (what `auto` picks for v2 models) |
|
|
140
|
+
| `mp3_48000_320` | MP3 48kHz 320kbps - highest quality MP3 |
|
|
141
|
+
| `mp3_44100_128` | MP3 44.1kHz 128kbps - smaller files |
|
|
142
|
+
| `pcm_48000` | Raw 16-bit PCM 48kHz, no header - for further processing |
|
|
143
|
+
| `opus_48000_128` | Opus 48kHz 128kbps in Ogg - efficient codec, small files |
|
|
144
|
+
|
|
145
|
+
## Content Restrictions
|
|
146
|
+
|
|
147
|
+
- Cannot reference specific artists, bands, or copyrighted lyrics. Describe the style instead
|
|
148
|
+
("1960s British invasion rock" rather than a band name).
|
|
149
|
+
- A rejected prompt returns 400 with ElevenLabs' `bad_prompt` detail, which includes a
|
|
150
|
+
`prompt_suggestion` with alternative phrasing. A rejected plan returns `bad_composition_plan`
|
|
151
|
+
with a `composition_plan_suggestion`. Retry with the suggestion.
|
|
152
|
+
|
|
153
|
+
## Error Handling
|
|
154
|
+
|
|
155
|
+
Errors return JSON with a `message`:
|
|
156
|
+
- **400 with an ElevenLabs message**: invalid parameters or restricted content (see "Content Restrictions").
|
|
157
|
+
- **400 "Provide prompt or composition_plan."**: send one of them.
|
|
158
|
+
- **402**: the organization does not have enough Letta credits for the longest song the request
|
|
159
|
+
allows (`credits_required`). Setting a shorter `music_length_ms` may help; otherwise tell the user
|
|
160
|
+
and do not retry.
|
|
161
|
+
- **500**: retry once, then report the failure.
|
|
162
|
+
|
|
163
|
+
If the connection drops partway through `/stream`, the file is truncated; only the audio
|
|
164
|
+
received is charged. Retry the request rather than sharing a partial song.
|
|
@@ -14,7 +14,8 @@ Instead of calling ElevenLabs with your own key, you call Letta's hosted endpoin
|
|
|
14
14
|
`POST /v1/audio/speech`. It forwards the request to ElevenLabs with Letta's key
|
|
15
15
|
and charges the organization's Letta credits, so you do not need an ElevenLabs
|
|
16
16
|
API key. The request body uses the same field names as ElevenLabs "Create
|
|
17
|
-
speech"
|
|
17
|
+
speech" (the voice ID and `output_format` go in the body), and the response is
|
|
18
|
+
the audio file itself, as with ElevenLabs.
|
|
18
19
|
|
|
19
20
|
## Quick Start
|
|
20
21
|
|
|
@@ -25,20 +26,9 @@ curl -sS -X POST "$base_url/v1/audio/speech" \
|
|
|
25
26
|
-H "Authorization: Bearer $LETTA_API_KEY" \
|
|
26
27
|
-H "Content-Type: application/json" \
|
|
27
28
|
-d '{"text":"Hello, welcome to ElevenLabs!","voice_id":"JBFqnCBsd6RMkjVDRZzb","model_id":"eleven_v4"}' \
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import base64, json
|
|
32
|
-
|
|
33
|
-
with open("speech-response.json") as f:
|
|
34
|
-
response = json.load(f)
|
|
35
|
-
if "audio_b64" not in response:
|
|
36
|
-
raise SystemExit(response.get("message", response))
|
|
37
|
-
|
|
38
|
-
with open("output.mp3", "wb") as f:
|
|
39
|
-
f.write(base64.b64decode(response["audio_b64"]))
|
|
40
|
-
print("saved output.mp3")
|
|
41
|
-
PY
|
|
29
|
+
--output output.mp3 \
|
|
30
|
+
--dump-header speech-headers.txt \
|
|
31
|
+
--write-out '%{http_code} %{content_type}\n'
|
|
42
32
|
```
|
|
43
33
|
|
|
44
34
|
Use the runtime-provided `LETTA_BASE_URL` and `LETTA_API_KEY` together. Build
|
|
@@ -46,9 +36,13 @@ URLs relative to `${LETTA_BASE_URL%/}` and do not hardcode
|
|
|
46
36
|
`https://api.letta.com`. If either variable is missing, the user needs to
|
|
47
37
|
authenticate with Letta Cloud; do not ask for an ElevenLabs key.
|
|
48
38
|
|
|
39
|
+
A `200` with an `audio/...` content type means `output.mp3` is the speech. Any
|
|
40
|
+
other status means `output.mp3` holds a JSON error with a `message` instead;
|
|
41
|
+
read it (see "Error Handling") and do not share the file.
|
|
42
|
+
|
|
49
43
|
Share the saved file the way your current surface supports: attach or upload it
|
|
50
|
-
to the conversation or channel you are replying in.
|
|
51
|
-
|
|
44
|
+
to the conversation or channel you are replying in. Keep credit amounts out of
|
|
45
|
+
replies unless the user asks about cost.
|
|
52
46
|
|
|
53
47
|
## Models
|
|
54
48
|
|
|
@@ -160,8 +154,9 @@ When generating long audio in multiple requests, the audio can have pops, unnatu
|
|
|
160
154
|
{"text": "And this continues the story.", "voice_id": "JBFqnCBsd6RMkjVDRZzb", "model_id": "eleven_v4", "previous_text": "This is the first part."}
|
|
161
155
|
```
|
|
162
156
|
|
|
163
|
-
Each response
|
|
164
|
-
|
|
157
|
+
Each response has a `request-id` header (saved by `--dump-header` above, e.g.
|
|
158
|
+
`grep -i '^request-id:' speech-headers.txt`). Instead of `previous_text`, you can
|
|
159
|
+
pass up to three earlier request IDs in `previous_request_ids` (and later ones in
|
|
165
160
|
`next_request_ids` when regenerating a middle part). Keep the same voice, model,
|
|
166
161
|
and voice settings for every part, split long text at sentence or paragraph
|
|
167
162
|
boundaries (each request takes up to 10,000 characters), and concatenate the
|
|
@@ -169,7 +164,7 @@ files in order, for example with `ffmpeg -f concat`.
|
|
|
169
164
|
|
|
170
165
|
## Output Formats
|
|
171
166
|
|
|
172
|
-
Pass `output_format` in the body.
|
|
167
|
+
Pass `output_format` in the body, and name the file to match the format.
|
|
173
168
|
|
|
174
169
|
| Format | Description |
|
|
175
170
|
|--------|-------------|
|
|
@@ -187,22 +182,6 @@ Pass `output_format` in the body.
|
|
|
187
182
|
| `opus_48000_64` | Opus 48kHz 64kbps - efficient codec, small files |
|
|
188
183
|
| `wav_44100` | WAV 44.1kHz - uncompressed with headers |
|
|
189
184
|
|
|
190
|
-
The Letta endpoint returns the whole file at once (as `audio_b64`); it does not stream.
|
|
191
|
-
|
|
192
|
-
## Response
|
|
193
|
-
|
|
194
|
-
```json
|
|
195
|
-
{
|
|
196
|
-
"model_id": "eleven_v4",
|
|
197
|
-
"voice_id": "JBFqnCBsd6RMkjVDRZzb",
|
|
198
|
-
"output_format": "mp3_44100_128",
|
|
199
|
-
"audio_b64": "<base64>",
|
|
200
|
-
"request_id": "Frhov0LQNC3M9HcHKY3t",
|
|
201
|
-
"characters": 46,
|
|
202
|
-
"billing": { "credits_charged": 4, "transaction_id": "...", "new_credit_balance": "..." }
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
185
|
## Error Handling
|
|
207
186
|
|
|
208
187
|
Errors return JSON with a `message`:
|
|
@@ -80,7 +80,9 @@ Cloud decisions service.
|
|
|
80
80
|
`phase` (progress group — use this inside concurrent stages), `schema`,
|
|
81
81
|
`json`, `model`, `effort` (`'low'` for mechanical stages, higher for the
|
|
82
82
|
hardest verify/judge stages), `allowedTools`, `systemPrompt` (extra system
|
|
83
|
-
prompt for this subagent), `
|
|
83
|
+
prompt for this subagent), `skills` (skill names whose full content is
|
|
84
|
+
loaded into the subagent's prompt; workers otherwise have no skills),
|
|
85
|
+
`timeoutMs` (default 10 minutes), `maxToolCalls`
|
|
84
86
|
(positive safe integer; default 1000 unique tool calls for this subagent),
|
|
85
87
|
`conversationId` (resume a worker — see "Diagnosing a run").
|
|
86
88
|
- `pipeline(items, stage1, stage2, ...)` → run each item through all stages
|