Skip to content

Migrating to 0.15

No rewrites needed. 0.15 is additive: one new capability tag in @effect-uai/core, three new packages (@effect-uai/telegram, @effect-uai/discord, @effect-uai/slack), and a small input-batching helper. Bump your dependencies, run typecheck, done.

No effect bump this release; the peer range stays >=4.0.0-rc.111 <5.0.0.

0.14 was additive too (the ImageGenerator capability) and has no page of its own. If you hit a compile error that looks like a rename, you are crossing an earlier breaking release. Apply the 0.13 page and the ones before it first.

What’s new (additive, no migration needed)

Messenger

Messenger puts your agent loop in a chat: one stream of what people say, five verbs for answering, and a provider layer per platform. Your loop, tools and history stay as they are.

import * as Messenger from "@effect-uai/core/Messenger"
const messenger = yield * Messenger.Messenger
const reply = (event: Messenger.InboundEvent) =>
event._tag === "Message" && event.addressed
? messenger
.post(Messenger.text(`You said: ${event.text}`, { replyTo: event.id }))
.pipe(Messenger.inConversation(event.conversation))
: Effect.void
yield * Stream.runForEach(messenger.events, reply)
  • events carries Message (with addressed: a DM, an @mention, or a reply to the bot), Command, Reaction and Action, each with the platform’s raw payload.
  • post, edit, react, typing (scoped) and stream (a Stream<string> delivered as one message that fills in as the model writes). A message is Messenger.text, Messenger.media over the core MediaSource, or Messenger.raw for the platform’s own payload.
  • The chat a verb targets is ambient: Messenger.inConversation(ref) once where a conversation starts, and every post underneath lands there, tools included. Posting outside a conversation is a compile error.
  • Text goes out verbatim. Your system prompt tells the model which markup to write; each provider page says which.
  • MessengerError covers the failures: RequestFailed, RateLimited, Unsupported, ConnectFailed, TransportClosed.
  • @effect-uai/core/MessengerAdapter is the adapter author’s side (splitForLimit, streamViaEdits), and @effect-uai/core/testing/MockMessenger replays scripted events and records every verb for unit tests.

Three providers, each a long-lived process with no public URL and no SDK:

Terminal window
pnpm add @effect-uai/telegram # Bot API, long-polling, HTML markup
pnpm add @effect-uai/discord # gateway websocket + REST v10, markdown
pnpm add @effect-uai/slack # Socket Mode + Web API, markdown, replies in threads

See Messenger, the provider pages for Telegram, Discord and Slack, and the messenger agent recipe.

Inbox.drainBurst

@effect-uai/core/Inbox has drainBurst(queue, settle): block on the first item, then keep taking while items keep arriving within settle, and hand back the batch. It is the debounce a long-lived loop reads its input with, so three quick messages become one turn.

import { drainBurst } from "@effect-uai/core/Inbox"
const incoming = yield * drainBurst(inbox, "800 millis")

It used to live inside the agentic-loop recipe; the recipe now imports it from core.