CLI / In-Process Agent
Build a small terminal chat loop without HTTP.
This example runs the agent in-process, keeps one durable thread open, and accepts terminal input until .exit.
// cli.ts
import { createAgentRuntime } from "@pai/core";
import { stdin as input, stdout as output } from "node:process";
import { createInterface } from "node:readline/promises";
import { agent } from "./server/agent";
import { storage } from "./server/storage";
const runtime = createAgentRuntime({
agent,
storage,
scopeKey: (identity) => identity.workspaceId,
});
const terminal = createInterface({ input, output });
try {
const pai = runtime.client({
identity: { id: "cli-user", workspaceId: "ws_cli" },
});
const threadId = process.argv[2]; // optional existing thread id
const thread = pai.thread(threadId ?? pai.newThreadId());
console.log(`Thread: ${thread.threadId}`);
console.log("Type a message, or .exit to quit.");
while (true) {
const prompt = (await terminal.question("> ")).trim();
if (prompt === ".exit") break;
if (!prompt) continue;
const run = await thread.send(prompt);
const state = await run.waitUntilIdle();
const reply = state.messages
.toReversed()
.find((message) => message.role === "assistant");
const text = reply?.parts
.filter((part) => part.type === "text")
.map((part) => part.text)
.join("");
console.log(text || "(no reply)");
}
} finally {
terminal.close();
await runtime.close();
}Run it without an argument to start a new thread. Pass an existing thread id as the first argument to continue that thread.