Adds features.memfs config key that controls whether the Letta Code CLI
receives --memfs or --no-memfs when creating/resuming SDK sessions. This
enables lettabot users to opt into git-backed memory filesystem (context
repositories) for persistent local memory sync.
- Config types: memfs?: boolean on AgentConfig.features, LettaBotConfig.features, BotConfig
- Bot wiring: baseSessionOptions() and createAgent() pass memfs to SDK when defined
- Main wiring: YAML config takes precedence, LETTABOT_MEMFS env var as fallback
- Legacy fix: conversations passthrough in single-agent normalization
- Tests: 3 memfs wiring tests (true/false/undefined), 2 conversations passthrough tests
- Docs: configuration.md section with known limitations, example YAML
Fixes#335
Written by Cameron and Letta Code
"The best way to predict the future is to implement it." -- David Heinemeier Hansson
Adds documentation for per-channel conversation routing and updated group configuration options. Fills the gap left by the implementation PRs.
Closes#304
Written by Cameron and Letta Code
"Documentation is a love letter that you write to your future self." -- Damian Conway
The reset-conversation CLI command was reading/writing the agent JSON file directly, missing the per-channel conversations map introduced with conversation routing. Now uses Store.clearConversation() which clears both the legacy conversationId and all per-channel conversation keys.
Also adds multi-agent awareness: prompts which agent to reset when multiple agents are configured.
Closes#316
Written by Cameron and Letta Code
"Debugging is twice as hard as writing the code in the first place." -- Brian Kernighan
Fixes reaction-only responses triggering spurious error messages. The <no-reply/> check now runs after directive parsing in both finalizeMessage() and the post-stream handler.
Fixes the case where <actions><react emoji="..." /></actions> as the full response would add the reaction but also send an error message.
Written by Cameron and Letta Code
"First, solve the problem. Then, write the code." -- John Johnson
Add config normalization, routing bindings, and per-agent instance management to support channel/account-aware dispatch with default agent fallback.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Three bugs fixed:
1. server.api is now the canonical location for API server config (port,
host, CORS). Users naturally nest api under server -- this now works.
Top-level api still accepted with a deprecation warning.
2. Onboarding no longer silently drops api and attachments config when
saving. Both interactive and non-interactive paths now preserve
unmanaged top-level fields from the existing config.
3. When YAML parsing fails, the log no longer misleadingly says
"Loaded from lettabot.yaml". A didLoadFail() flag enables accurate
status reporting without changing 17+ loadConfig() call sites.
Written by Cameron ◯ Letta Code
"The map is not the territory, but a good map sure helps you find port 6702."
Consolidates listeningGroups and groups.requireMention into a single
groups config with explicit mode per group. Backward compatible --
legacy formats auto-normalize with deprecation warnings.
- Add shared group-mode.ts with isGroupAllowed/resolveGroupMode helpers
- Update all 5 channel adapters to use mode-based gating
- Default to mention-only for configured entries (safe), open when no config
- Listening mode now set at adapter level, bot.ts has legacy fallback
- Fix YAML large-ID parsing for groups map keys (Discord snowflakes)
- Add migration in normalizeAgents for listeningGroups + requireMention
- Add unit tests for group-mode helpers + update all gating tests
- Update docs, README, and example config
Closes#266
Written by Cameron and Letta Code
"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery
* feat: default new configs to multi-agent format
Onboarding and non-interactive config generation now emit the
agents[] array format instead of the legacy agent/channels/features
flat structure. This makes adding a second agent a simple array
append rather than a config format migration.
Existing legacy configs continue to work -- normalizeAgents()
handles both formats at runtime.
Written by Cameron and Letta Code
"The future is already here -- it's just not very evenly distributed." -- William Gibson
* test: add save/load roundtrip tests for agents[] config format
Tests the actual YAML serialization path:
- agents[] written without legacy agent/channels at top level
- roundtrip through save + load + normalizeAgents preserves all fields
- global fields (providers, transcription) stay at top level
Written by Cameron and Letta Code
"Programs must be written for people to read, and only incidentally for machines to execute." -- Abelson & Sussman
* feat: eagerly create agent during onboarding
When the user picks "Create new agent", the agent is now created
immediately (with spinner) rather than deferred to first message.
The agent ID is written directly to lettabot.yaml, making the
config file the single source of truth.
Creates the agent with system prompt, memory blocks, selected model,
display name, skills, and disables tool approvals -- same setup that
bot.ts previously did lazily on first message.
Graceful fallback: if creation fails, falls back to lazy creation.
Written by Cameron and Letta Code
"Make it work, make it right, make it fast." -- Kent Beck
Tool call events between assistant messages were invisible in [Stream]
debug output, making it hard to understand message finalization timing.
- Add sawNonAssistantSinceLastUuid tracking to warn when assistant UUID
changes with no visible tool_call/reasoning events in between
- Replace [Bot] tool logging with [Stream]-prefixed structured summaries
(>>> TOOL CALL, <<< TOOL RESULT) for greppable output
- Bridge DEBUG=1 to DEBUG_SDK=1 so SDK-level dropped wire messages are
visible when debugging
Written by Cameron ◯ Letta Code
"The stream does not resist the rock; it flows around it, revealing its shape." -- Unknown
WhatsApp and Signal already had groups config with requireMention and
group allowlists. This brings the same pattern to the remaining three
channels, giving operators consistent control over which groups the bot
participates in and whether mentions are required.
- New `groups` config for Telegram, Discord, Slack (per-group allowlist
with requireMention, wildcard support)
- Telegram: standalone gating module with entity, text, command, and
regex mention detection; applied to text, voice, and attachment handlers
- Discord: inline gating using native message.mentions API
- Slack: gating in message handler (drops non-mentions) and app_mention
handler (allowlist check); helper methods on adapter
- Signal: pass wasMentioned through to InboundMessage (was detected but
never forwarded)
- Config wiring: groups/mentionPatterns forwarded from main.ts to all
adapter constructors
- 17 new tests for Telegram gating
Written by Cameron ◯ Letta Code
"Even in the group chat of life, sometimes you gotta be @mentioned
to know the universe is talking to you." — Ancient Internet Proverb