creating-letta-code-channels

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Creating Letta Code channels

创建Letta Code渠道

Use this when adding or debugging Letta Code channel support.
适用于添加或调试Letta Code渠道支持的场景。

First choice

首选方案

  • User plugin (
    ~/.letta/channels/<id>/
    ) for headless experiments, community plugins, and fast workflow tests.
  • First-party channel (
    src/channels/<id>/
    ) when the channel needs bespoke Desktop UI, custom account snapshots, Slack/Discord-style auto-routing, rich protocol fields, or migration/compatibility shims.
User plugins cannot shadow first-party ids:
telegram
,
slack
, and
discord
are ignored under
~/.letta/channels/
. Use ids like
telegram-test
,
whatsapp-community
, or
custom-chat
.
  • 用户插件
    ~/.letta/channels/<id>/
    ):适用于无头实验、社区插件以及快速工作流测试。
  • 官方渠道
    src/channels/<id>/
    ):当渠道需要定制化桌面UI、自定义账户快照、Slack/Discord风格的自动路由、丰富的协议字段或迁移/兼容性垫片时使用。
用户插件不能覆盖官方ID:
telegram
slack
discord
~/.letta/channels/
下会被忽略。请使用类似
telegram-test
whatsapp-community
custom-chat
的ID。

Core workflow

核心工作流

  1. Work in
    ~/letta/letta-code
    or a worktree.
  2. Read
    src/channels/README.md
    on branches with dynamic plugins.
  3. For a user plugin, create:
    • ~/.letta/channels/<id>/channel.json
    • ~/.letta/channels/<id>/plugin.mjs
    • ~/.letta/channels/<id>/accounts.json
  4. Always implement
    messageActions
    if agents should reply via
    MessageChannel
    .
  5. Start with
    dmPolicy: "pairing"
    for testing, or
    allowlist
    /
    open
    for known headless deployments.
  6. Test all four legs:
    • plugin discovery/import
    • inbound
      adapter.onMessage(msg)
      to route/pairing
    • routed channel notification reaches the agent
    • outbound
      MessageChannel
      calls
      messageActions.handleAction
      adapter.sendMessage
  7. Run targeted tests, then
    bun run typecheck
    ,
    bun run lint
    ,
    bun run build
    .
  1. ~/letta/letta-code
    或工作树中开展工作。
  2. 阅读支持动态插件分支上的
    src/channels/README.md
    文档。
  3. 若创建用户插件,需生成以下文件:
    • ~/.letta/channels/<id>/channel.json
    • ~/.letta/channels/<id>/plugin.mjs
    • ~/.letta/channels/<id>/accounts.json
  4. 如果Agent需要通过
    MessageChannel
    回复,务必实现
    messageActions
  5. 测试阶段先设置
    dmPolicy: "pairing"
    ,对于已知的无头部署环境,可使用
    allowlist
    open
  6. 测试全部四个环节:
    • 插件发现/导入
    • 入站消息
      adapter.onMessage(msg)
      的路由/配对
    • 路由后的渠道通知送达Agent
    • 出站消息通过
      MessageChannel
      调用
      messageActions.handleAction
      adapter.sendMessage
  7. 运行针对性测试,然后执行
    bun run typecheck
    bun run lint
    bun run build

References

参考文档

Read only what is needed:
  • references/user-plugins.md
    — dynamic plugin manifest/account/runtime/headless flow and gotchas.
  • references/first-party-channels.md
    — first-party channel file cascade and safety checks.
  • references/testing.md
    — smoke-test checklist and commands.
按需阅读以下文档:
  • references/user-plugins.md
    — 动态插件清单/账户/运行时/无头流程及注意事项。
  • references/first-party-channels.md
    — 官方渠道文件层级及安全检查。
  • references/testing.md
    — 冒烟测试清单及命令。

Scaffold helper

脚手架工具

Use the bundled scaffold for a minimal user plugin skeleton. Replace
<path-to-this-skill>
with this skill directory path:
bash
npx tsx <path-to-this-skill>/scripts/scaffold-user-channel-plugin.ts \
  my-channel "My Channel" \
  --runtime-package some-sdk@1.0.0 \
  --runtime-module some-sdk
It creates
channel.json
,
plugin.mjs
, and
accounts.example.json
. Replace the TODO inbound/outbound implementation with the real SDK calls.
使用内置脚手架生成最小化的用户插件骨架。将
<path-to-this-skill>
替换为该技能目录路径:
bash
npx tsx <path-to-this-skill>/scripts/scaffold-user-channel-plugin.ts \
  my-channel "My Channel" \
  --runtime-package some-sdk@1.0.0 \
  --runtime-module some-sdk
它会生成
channel.json
plugin.mjs
accounts.example.json
。将TODO标记的入站/出站实现替换为真实的SDK调用。

Hard lessons

经验总结

  • MessageChannel
    silently feels broken if
    plugin.messageActions
    is missing. Every plugin that should reply needs
    describeMessageTool()
    and
    handleAction()
    .
  • For public channels, suppress tool approval/control prompts unless there is verified operator routing. Posting approval prompts publicly leaks tool input and invites forged
    approve
    replies.
  • User plugin runtime resolution must not count parent/dev
    node_modules
    . Runtime modules should resolve from explicit runtime dirs only.
  • Headless pairing is CLI-first:
    letta channels pair --channel <id> --code <code> --agent <agent-id> --conversation <conversation-id>
    .
  • Running listeners reload
    pairing.yaml
    and
    routing.yaml
    on the next inbound miss; restart only when adapter/account config itself changed.
  • 如果缺少
    plugin.messageActions
    MessageChannel
    会看似无响应。所有需要回复的插件都必须实现
    describeMessageTool()
    handleAction()
  • 对于公开渠道,除非有已验证的操作员路由,否则应禁用工具审批/控制提示。在公开渠道发布审批提示会泄露工具输入,并可能招致伪造的
    approve
    回复。
  • 用户插件运行时解析不能依赖父目录/开发环境的
    node_modules
    。运行时模块应仅从明确指定的运行时目录解析。
  • 无头配对以CLI优先:
    letta channels pair --channel <id> --code <code> --agent <agent-id> --conversation <conversation-id>
  • 运行中的监听器会在下一次入站消息未匹配时重新加载
    pairing.yaml
    routing.yaml
    ;仅当适配器/账户配置本身发生变化时才需要重启。