Tablebox ドキュメントサイト English

Agent

Agent は、人が声でも文字でも話せて、遮ることもできる AI です。開発者の AI プロバイダのアカウントで、直接聞いて話すモデル(OpenAI Realtime か Gemini Live)を使って動き、呼ばれたブロードキャストを聞き、声と文字で答え、アプリのツールを呼び、アプリが渡す手がかりを読みます。

パス

{source} はブロードキャストのパスで、ふつうは呼ぶ人自身のもの(alice/camera.hang)です。

書く人 パス トラック 中身
呼ぶ人 {source} hang のカタログと音声 Agent が聞く声: 最初の音声のレンディション
呼ぶ人 {source} context.json(任意) JSON スナップショットのトラック: モデルへの手がかり
呼ぶ人 {source} input.json(任意) 各フレームが一つの JSON オブジェクト: 入力した文 {"text": string}、またはツールの結果 {"call": id, "output": value}
Agent .agent/{source} hang のカタログと音声 Agent の声(Opus)
Agent 同じ transcript.json 各フレーム {"id", "role": "user" or "agent", "text", "final": boolean, "interrupted"?: true}。同じ id の後のフレームが、その項目の文を置き換える
Agent 同じ calls.json 各フレームがツールの呼び出し {"id", "name", "arguments": object}
Agent 同じ status.json JSON スナップショットのトラック {"state", "code"?, "message"?}。state は connecting、listening、thinking、speaking、failed のどれか

.agent/{source} を読むと Agent が {source} を聞くので、{source} と同じように許してください。subscribe に .agent/{id}/** があれば、各自は自分のブロードキャストで Agent を呼べます。transcript.json と calls.json は MoQ の JSON ストリーム(json.Stream)なので、後から来た読み手もそれまでの会話を読めます。

TypeScript(ブラウザー) · agent.ts
// A typed conversation with the Agent: messages go on input.json of {me}/chat, and the
// conversation comes from .agent/{me}/chat.
import { type Connection, json } from 'tablebox.io';

interface Item { id: string; role: 'user' | 'agent'; text: string; final: boolean; interrupted?: true }

export async function chat(connection: Connection, me: string, show: (item: Item) => void) {
  const input = connection.publish(`${me}/chat`).createTrack('input.json');
  const agent = await connection.read(`.agent/${me}/chat`);
  const transcript = new json.Stream.Consumer<Item>({ track: agent.track('transcript.json').subscribe() });
  // A later item with the same id replaces that item's text.
  void (async () => { for await (const item of transcript) show(item); })();
  return (text: string) => input.writeJson({ text });
}

話す

.agent/{source} のどれかのトラックを読むと、{source} の会話が一つ始まり、そのパスの読み手全員で共有します。会話はパスが読まれている間続き、最後の読み手が去ってから 20 秒で終わります。Agent は元の音声と入力した文を聞き、声と文字で答えます。両方の言葉は、聞き取られ話されるのに合わせて transcript.json に出ます。声で話すには、使い始めるの {id}/camera.hang のように、マイクを載せたブロードキャストで呼び、.agent/{id}/camera.hang を公式のプレーヤーで再生します。音声のない元とは、入力した文だけで話します。

Agent が話している間に呼ぶ人が話し始めるか文を送ると、Agent はすぐに話すのをやめ、その答えに interrupted を付けます。プロバイダが長さの上限でセッションを終えると、Agent は新しいセッションを開き、それまでの会話を文として渡します。

ツールと手がかり

モデルは AGENT_TOOLS にあるツールを呼びます。呼び出しはそれぞれ calls.json に出て、アプリはその id を付けて input.json で答えます。10 秒以内に答えが来なければ、失敗した呼び出しとしてモデルに届きます。context.json の最新の値は、その JSON の 64 KiB までが、変わるたびにモデルに渡されます。

環境変数

変数 意味
AGENT_PROVIDER openai(OpenAI Realtime、既定)か gemini(Gemini Live)
OPENAI_API_KEY, GEMINI_API_KEY 選んだプロバイダのキー。必須
AGENT_MODEL プロバイダのモデル。設定しなければ OpenAI は gpt-realtime-2.1、Gemini は gemini-3.8-live
AGENT_VOICE プロバイダの声。設定しなければプロバイダの既定
AGENT_INSTRUCTIONS モデルに渡す指示
AGENT_TOOLS {"name", "description", "parameters"} の JSON 配列。parameters は JSON Schema。設定しなければツールなし

環境変数はプロジェクトのものなので、一つの設定がプロジェクトのすべての会話に使われます。

失敗