betalyra/effect-uai
betalyra/effect-uai has 77 GitHub stars and 5 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 08:26 UTC. Last push 2026-11-11.
What you can do
- Explicit control. No black-box magic. You stay in full control of your agent loop.
- Built on Effect. Retries, streams, concurrency, errors: handled by Effect, not reinvented.
- Composable primitives. Small building blocks you assemble into your own agentic loops.
- Recipes for the hard parts. Copy-paste solutions for model council, auto-compaction, pause and resume, and more.
Measured star growth
- in 24h
- 0
- in 7 days
- Collecting history
- in 15 days
- Collecting history
- in 1 month
- Collecting history
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
About
Effect building blocks for agentic ai
AIREADME.md
Original
Uai \ wai \. Mineiro Portuguese, all-purpose interjection.
Low-level primitives for building AI agents with Effect.
effect-uai is not a framework. There's no runtime to learn, no orchestrator to override, no graph to fight. You get typed streaming primitives (one turn, one tool call) and compose the loop yourself.
OpenAI Responses, Anthropic, Gemini, Mistral, and any OpenAI-compatible
gateway normalize to one TurnEvent union. State is yours. The loop is yours.
Status
While we're in 0.x, minor releases may include breaking changes.
Each one ships with a migration guide
written in operator form ("if you see X, write Y"), so pointing Claude
Code at the page makes upgrades mechanical.
Why effect-uai
Most agent libraries decide how your loop works: state shape, retry policy, tool dispatch, cancellation. When you need something they didn't plan for (approval gates, mid-stream cancel, fallback, auto-compaction), you fight the framework.
effect-uai owns the wire (HTTP, SSE, event normalization, validation).
You own the policy. They meet at a Stream<TurnEvent> and a plain
state record.
Features
- Explicit control. No black-box magic. You stay in full control of your agent loop.
- Built on Effect. Retries, streams, concurrency, errors: handled by Effect, not reinvented.
- Composable primitives. Small building blocks you assemble into your own agentic loops.
- Recipes for the hard parts. Copy-paste solutions for model council, auto-compaction, pause and resume, and more.
- Streaming first. Everything's a stream you can transform, filter, and collect when ready.
- Typed errors. Match
RateLimited,Unavailable, orTimeoutdirectly. No string parsing. - Carry your own state. History, budget, scratchpad. Track whatever your agent needs. It's just a value.
Quick taste
The canonical agent loop: stream a turn, run any tools the model asks for, append the outputs, continue until it stops.
export const conversation = loop(initial, (state) =>
Effect.gen(function* () {
const oai = yield* Responses // swap for Anthropic / Gemini any turn
return oai
.streamTurn({ history: state.history, model, tools: toolkit }) // stream text, reasoning, tool events
.pipe(
onTurnComplete((turn) => {
const calls = Turn.getToolCalls(turn) // approve, deny, audit, batch (it's your code)
if (calls.length === 0) return stop() // stop on a final answer, a budget, your call
return Toolkit.run(toolkit, calls).pipe(
// run typed Effect tools
Toolkit.next(toolkit, state, turn), // fold results back into your state
)
}),
)
}),
)
For tools, approvals, multi-turn loops, sandboxes, and cross-provider fallback, see the docs or the recipes.
Packages
| Package | What it is |
|---|---|
@effect-uai/core |
The primitives: Loop, LanguageModel, Tool, Toolkit, Items, Turn, Transcriber, SpeechSynthesizer, RealtimeSession, EmbeddingModel, Reranker, DecisionModel, Chunker, Tokenizer, MusicGenerator, ImageGenerator, WebSearch, WebRead, Browser, Sandbox, DeepResearch, Messenger. No provider deps. |
@effect-uai/retrieval |
Retrieval-pipeline utilities: text chunking with provenance offsets, reciprocal rank fusion, and a Hugging Face tokenizer layer. |
@effect-uai/responses |
OpenAI Responses provider. Implements LanguageModel over OpenAI's /v1/responses endpoint. |
@effect-uai/chat-completions |
Reusable /chat/completions LanguageModel base. Point it at any compatible gateway: OpenRouter, Requesty, Groq, Together, self-hosted. |
@effect-uai/anthropic |
Anthropic Messages provider, including extended thinking. |
@effect-uai/google |
Google Gemini: language model, embeddings, speech (sync STT + TTS), Gemini Live realtime sessions (voice and camera), Nano Banana image generation, and Lyria music generation. |
@effect-uai/mistral |
Mistral: LanguageModel (chat) plus Voxtral speech: realtime + batch STT and TTS. One brand for a full STT to LLM to TTS pipeline. |
@effect-uai/openai |
OpenAI brand package: Responses language models, embeddings, deep research, image generation (gpt-image-2, with partial-image streaming), speech (Transcriber sync + realtime WS, Synthesizer sync + chunked HTTP), and OpenAI Realtime speech-to-speech sessions. |
@effect-uai/fal |
Fal image generation: FLUX, Seedream, Qwen Image, Muse and the open-weights field behind one key. The model id is an endpoint path. |
@effect-uai/elevenlabs |
ElevenLabs: Scribe v2 Realtime STT, Flash v2.5 TTS with incremental-text-in WS, and music generation. |
@effect-uai/inworld |
Inworld speech: first-party STT/TTS plus router-style passthroughs (AssemblyAI / Soniox / Groq Whisper). |
@effect-uai/jina |
Jina embeddings (dense, sparse ELSER, multivector ColBERT-style), reranking (text + image), and web read. |
@effect-uai/typesafe-ai |
TypeSafe AI Jev DecisionModel: typed classify, rate and probability questions about one input, answered with probabilities in one call. |
@effect-uai/perplexity |
Perplexity web search: fast, current-events snippets for grounding an LLM. |
@effect-uai/exa |
Exa: neural / semantic web search ranked by relevance score, plus web read. |
@effect-uai/tavily |
Tavily: web search with search-depth control, plus web read. |
@effect-uai/firecrawl |
Firecrawl web read: fetch a URL and get back clean, LLM-ready markdown. |
@effect-uai/browser |
Generic Chrome DevTools Protocol browser provider. Drive a real page as a tool. |
@effect-uai/mcp |
Model Context Protocol client. Any MCP server's tools become an ordinary Toolkit. |
@effect-uai/microsandbox |
Local Firecracker microVM sandboxes via microsandbox. Run untrusted code in isolation. |
@effect-uai/deno |
Hosted Firecracker microVM sandboxes on Deno Deploy. No local infra to run. |
@effect-uai/telegram |
Telegram Messenger: your agent as a bot over the Bot API. DMs, group mentions and commands in, streamed HTML replies, media and reactions out. Long-polling, no SDK. |
@effect-uai/discord |
Discord Messenger: one gateway websocket plus the v10 REST API. DMs, mentions, threads and buttons in, streamed markdown replies, media and reactions out. No discord.js. |
@effect-uai/slack |
Slack Messenger: Socket Mode plus the Web API. Mentions, DMs, slash commands and buttons in, streamed markdown replies in a thread, files and reactions out. No Bolt. |
@effect-uai/ui |
Agentic UI: a resumable run-event protocol, projection from your loop, and client folds and Effect atoms that turn it into typed state for any framework (React, FoldKit, plain DOM). |
@effect-uai/ai-sdk |
Vercel AI SDK compatibility: render a TurnEvent stream as a useChat UI Message Stream. |
Each provider is its own package - edge / browser builds only pull in what you actually use.
Repo layout
.
├── packages/
│ ├── core/ # @effect-uai/core - primitives, no provider deps
│ ├── ui/ # @effect-uai/ui - agentic UI protocol, folds, atoms
│ ├── retrieval/ # @effect-uai/retrieval - chunking, rank fusion, tokenizer
│ ├── compat/
│ │ └── ai-sdk/ # @effect-uai/ai-sdk - Vercel AI SDK UI Message Stream
│ └── providers/
│ ├── responses/ # @effect-uai/responses - OpenAI Responses
│ ├── chat-completions/ # @effect-uai/chat-completions - gateway base
│ ├── anthropic/ # @effect-uai/anthropic
│ ├── google/ # @effect-uai/google - Gemini + speech + Live + images + Lyria
│ ├── mistral/ # @effect-uai/mistral - LLM + Voxtral speech (STT/TTS)
│ ├── openai/ # @effect-uai/openai - Responses + embeddings + speech + realtime + images
│ ├── fal/ # @effect-uai/fal - image generation (FLUX, Seedream, Qwen)
│ ├── elevenlabs/ # @effect-uai/elevenlabs - speech + music
│ ├── inworld/ # @effect-uai/inworld - speech
│ ├── jina/ # @effect-uai/jina - embeddings + rerank + web read
│ ├── typesafe-ai/ # @effect-uai/typesafe-ai - Jev decision model
│ ├── perplexity/ # @effect-uai/perplexity - web search
│ ├── exa/ # @effect-uai/exa - web search + web read
│ ├── tavily/ # @effect-uai/tavily - web search + web read
│ ├── firecrawl/ # @effect-uai/firecrawl - web read
│ ├── browser/ # @effect-uai/browser - CDP browser control
│ ├── mcp/ # @effect-uai/mcp - MCP client
│ ├── microsandbox/ # @effect-uai/microsandbox - local sandboxes
│ ├── deno/ # @effect-uai/deno - hosted sandboxes
│ ├── telegram/ # @effect-uai/telegram - Messenger over the Bot API
│ ├── discord/ # @effect-uai/discord - Messenger over gateway + REST
│ └── slack/ # @effect-uai/slack - Messenger over Socket Mode + Web API
├── recipes/ # 40+ worked recipes (type-checked, tested) covering
│ # tools, approvals, fallback, voice, realtime, retrieval, MCP, chat bots, …
├── recipes-extras/ # 3 recipes needing extra infra (agentic-search,
│ # contextual-retrieval, sandbox-code-interpreter)
├── docs/ # Source for the docs site (concepts, recipes, providers)
├── webpage/ # Astro/Starlight site that renders docs/
├── skills/ # Agent skills that teach a coding agent this library
├── examples/ # Standalone apps (Next.js, TanStack Start, FoldKit); installed on their own
└── integration-tests/ # Live-system smoke tests; run manually, not part of CI
A recipe folder typically contains:
recipe.ts- the building blocks (tools, state, body), reusable in testsapp.ts- provider wiring and rendering, runtime-agnosticrun.ts- the entry point; attaches the platformHttpClientfor whichever runtime starts itrecipe.test.ts- vitest tests againstMockProviderREADME.md- the page that's mirrored in the docs site
Docs / learn
Full docs: https://effect-uai.com
Prefer video? Watch the 47 minute intro first.
Recommended reading order:
- One turn is a stream - the smallest provider-agnostic primitive.
- Basic usage - the core agent harness: state, stream, tools, continuation.
- The loop primitive - what
loopis, its step type, andonTurnComplete. - Items and turns - the conversation as a flat list, the assembled turn, the event stream.
- Tools and toolkits -
Tool.make(an Effect or a Stream, typed outputs and errors),Tool.declare,Toolkit.run/Toolkit.next,ToolEvent. - MCP - point at an MCP server and its tools become a
Toolkit.
Then dip into recipes for whatever pattern you need.
Local development
pnpm install
pnpm test # vitest run across all workspaces
pnpm typecheck # tsc --noEmit
To run a recipe end-to-end against a real provider (here any OpenAI-compatible gateway; each recipe's README lists its flags and keys):
LLM_API_KEY=... pnpm tsx recipes/basic-usage/run.ts \
--base-url https://router.requesty.ai/v1 --model moonshotai/kimi-k3 --provider requesty
Nix dev shell (optional)
This repo ships a flake.nix that provides a dev shell with the exact
toolchain CI uses - Node 24, the pinned pnpm version (via corepack), and
Deno for the integration tests. It is 100% optional: if you already
have Node and pnpm installed, ignore this entirely and use the commands
above.
If you do use Nix with flakes enabled:
nix develop # drops you into a shell with node, pnpm and deno
The repo also ships an .envrc, so with direnv
installed the shell loads automatically when you cd in - just run
direnv allow once. Without direnv the file is inert and ignored.
Contributing
Development happens on the dev branch; main tracks the latest release. Base
your branch and pull request on dev.
- Open an issue first for anything that changes the design: a new core primitive, a change to an existing API, a different way of doing something the library already does. We'd rather agree on the shape before you write the code, so you don't spend time on work we can't adopt as is or would have to change substantially.
- Pull requests are welcome for bug fixes, docs fixes and small improvements, and for additions that follow the existing design: a new provider, a capability for an existing service, a recipe. Look at a neighbouring package or recipe and match its shape.
Before you open a pull request, run pnpm typecheck and pnpm test. If it
changes a published package, add a changeset with pnpm changeset.
Contributors
Thanks to everyone who has contributed to effect-uai.
License
MIT - see LICENSE.