Klippy is an agent now, but nothing talks to it. This lesson gives it a chat in your terminal: pnpm chat sam opens a conversation with the Klippy called sam, and replies stream in word by word.
Verified agents 0.33.0ai 7.0.162tsx 4.23.15
Start from c-03 on GitHub. Starting here, or behind? Get the code at that tag:
git clone https://github.com/ryanyogan/klippy cd klippy git checkout c-03
1. A script again
The chat is a script on your machine, like last lesson's loop, so tsx comes back. From klippy/:
pnpm --filter agent add -D --save-exact tsx@4.23.15In apps/agent/package.json, add "chat": "tsx --env-file=.dev.vars scripts/chat.ts" to scripts, and put "scripts/**/*.ts" back in tsconfig.json's include. The script reads KLIPPY_TOKEN from your .dev.vars.
2. Open one WebSocket
A chat is many messages back and forth, with replies arriving in pieces. A WebSocket suits that: one connection, kept open, messages both ways. Make apps/agent/scripts/chat.ts:
KLIPPY_URLsays where Klippy runs. It defaults to wrangler's port, 8787; set it to your deployed address later.AgentClientopens the socket to/agents/klippy/<name>. The token goes inquery, the one place last lesson allowed it.WebSocketChatTransportspeaks the chat protocol over that socket.
3. Start from the chat Klippy already has
The conversation lives in the agent, not in your script. So load it first:
get-messages is a route every chat agent has. It's plain HTTP, so the token goes in the header.
4. Read your lines, send them, print the stream
The rest of the file is the chat itself:
Each line you type becomes a user message, added to the history.
sendMessagessends the conversation; the reply comes back as a stream of chunks.readUIMessageStreamturns the chunks into a growing message. Each step gives the whole reply so far, so the script prints only the new characters (slice(printed)).
The agent stores every reply too: if your connection drops mid-reply, a client that reconnects can pick it up where it left off. This script doesn't show that, but the agent does it for you.
5. Talk to Klippy
Terminal 1, from klippy/: pnpm dev. Terminal 2, in apps/agent:
pnpm chat samOur run. The free Workers AI fallback answered, not Claude (the gateway had no Anthropic key). Our dev server was on port 8801, hence KLIPPY_URL, and we piped the lines in, so they don't echo after you>. Typed by hand, they do.
Then a new run with the same name, and one with a different name:
sam kept its chat across runs; alex is a different Klippy, with its own. That's short-term memory: the chat itself. Next lesson adds memory that outlives it.
If you see Klippy said 401, KLIPPY_TOKEN in .dev.vars doesn't match the one the Worker was started with: restart pnpm dev. If it hangs, check KLIPPY_URL points at the port pnpm dev printed.
No new tests this time: the script is a client, pnpm typecheck checks it, and the agent's tests are last lesson's.
Your code matches tag c-04 (changes from c-03).