Umwelten
Every AI model lives in its own perceptual bubble — its Umwelt. Umwelten lets you build agent environments that observe, measure, and understand themselves.
Habitat — a living container for AI agents: persona, tools, memory, sessions, sub-agents, multiple interfaces (CLI, Telegram, Discord, web). Evaluation — systematic model assessment that reveals how models actually see the world. TypeScript / Node 20+.
See for yourself
git clone https://github.com/The-Focus-AI/umwelten.git
cd umwelten && pnpm install && cp env.template .env
# Add your GOOGLE_GENERATIVE_AI_API_KEY to .env
# `umwelten search` requires ripgrep (rg) on PATH: brew install ripgrep# Start an agent environment
npx umwelten habitat
# Same prompt, multiple providers, one command
npx umwelten eval run \
--prompt "Explain why the sky is blue" \
--models "google:gemini-3-flash-preview,openrouter:openai/gpt-5.4-nano" \
--id "sky-test" --concurrent
# 76% of models fail this common-sense question
dotenvx run -- pnpm tsx examples/evals/car-wash.ts
dotenvx run -- pnpm tsx examples/evals/reasoning.ts
Can a model write exactly 12 words?
dotenvx run -- pnpm tsx examples/evals/instruction.ts
## Programmatic usage
import { Stimulus, Interaction, Habitat, EvalSuite } from "umwelten";
// Talk to any model const stimulus = new Stimulus({ role: "helpful assistant" }); const interaction = new Interaction( { name: "gemini-3-flash-preview", provider: "google" }, stimulus, ); const reply = await interaction.chat("Hello");
// Build an agent environment const habitat = await Habitat.create({ workDir: "./my-agent" }); const { interaction: ix } = await habitat.createInteraction(); await ix.chat("List my agents");
// Evaluate models const suite = new EvalSuite({ name: 'quick-test', stimulus: { role: 'helpful assistant', temperature: 0.3 }, models: [{ name: 'gemini-3-flash-preview', provider: 'google' }], tasks: [{ id: 'math', prompt: 'What is 2+2?', maxScore: 1, verify: (r) = ({ score: r.trim() === '4' ? 1 : 0, details: r.trim() }), }], }); await suite.run();
## Web applications
Habitats also drive HTTP chat. `@umwelten/habitat` exposes `startWebServer` — the web peer to the Discord and Telegram adapters. It speaks the [Vercel AI SDK UI Message Stream Protocol](https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol), so any React frontend using `@ai-sdk/react`'s `useChat` connects with no glue code. Streaming text, tool calls, and tool results all flow through the same `ChannelBridge` that every other channel uses.
import { Habitat } from 'umwelten'; import { startWebServer } from '@umwelten/habitat';
const habitat = await Habitat.create({ workDir: './my-habitat' }); await startWebServer({ habitat, auth: 'dev', // or a custom AuthProvider staticRoot: './public', // built SPA port: 3000, });
Generative UI comes via a `renderUi` tool that ships a [json-render](https://json-render.dev) Spec through the tool-call channel — the client renders it with `@json-render/react`. See [`examples/umwelten-web-demo/`](examples/umwelten-web-demo/) for the reference app (`useChat` + thread sidebar + tool-call cards + renderUi).