Ink terminal
Same controller, rendered in your terminal via Ink.
'use client'import { useEffect, useMemo, useState } from 'react'import { createChatController } from '@agentskit/core'import type { AdapterFactory, ChatController, ChatState, StreamChunk,} from '@agentskit/core'const REPLIES = [ 'Sunny saturday, showers sun → mon. Pack a light jacket.', '12 units in LAX warehouse, ships same-day.', 'Three options under $320. Delta 06:15 is fastest nonstop.',]const inkAdapter: AdapterFactory = { capabilities: { streaming: true, tools: false }, createSource: () => { let i = 0 return { stream: async function* (): AsyncIterableIterator<StreamChunk> { const reply = REPLIES[i % REPLIES.length] i += 1 for (const ch of reply) { await new Promise(r => setTimeout(r, 18)) yield { type: 'text', content: ch } } yield { type: 'done' } }, abort() {}, } },}const PROMPTS = [ 'weather in tokyo this weekend', 'inventory for sku h-42', 'flights LAX to NYC tomorrow',]export function InkTerminal() { const controller: ChatController = useMemo( () => createChatController({ adapter: inkAdapter, initialMessages: [] }), [], ) const [state, setState] = useState<ChatState>(controller.getState()) const [idx, setIdx] = useState(0) useEffect(() => controller.subscribe(() => setState(controller.getState())), [controller]) const send = () => { void controller.send(PROMPTS[idx % PROMPTS.length]) setIdx(idx + 1) } const reset = () => { controller.setMessages([]) setIdx(0) } const lines: Array<{ kind: 'user' | 'assistant'; text: string }> = [] for (const m of state.messages) { if (m.role === 'user' || m.role === 'assistant') { lines.push({ kind: m.role, text: m.content }) } } return ( <div data-ak-example className="flex flex-col gap-3 rounded-lg border border-ak-border bg-ak-surface p-4"> <div className="flex items-center justify-between font-mono text-xs"> <span className="text-ak-graphite">@agentskit/core · createChatController · same controller, terminal renderer</span> <span className="text-ak-graphite">@agentskit/ink uses this</span> </div> <div className="flex items-center gap-2"> <button type="button" onClick={send} disabled={state.status === 'streaming'} className="rounded-md bg-ak-blue/20 px-3 py-1.5 font-mono text-xs text-ak-blue disabled:opacity-50" > {state.status === 'streaming' ? 'streaming…' : '▶ send next prompt'} </button> <button type="button" onClick={reset} className="rounded-md border border-ak-border px-3 py-1.5 font-mono text-xs text-ak-graphite" > reset </button> <span className="ml-auto font-mono text-[10px] text-ak-graphite"> status: {state.status} </span> </div> <div className="overflow-hidden rounded-lg border border-ak-border bg-black shadow-lg"> <div className="flex items-center justify-between border-b border-ak-border bg-ak-surface px-3 py-1.5"> <div className="font-mono text-xs text-ak-foam">~/agentskit · ink · tty</div> <span className="font-mono text-[10px] text-ak-green">● {state.status === 'streaming' ? 'streaming' : 'idle'}</span> </div> <pre className="min-h-[180px] px-3 py-2 font-mono text-[11px] leading-relaxed"> {lines.length === 0 && ( <span className="text-[#a6adc8]">{'> waiting for input…'}</span> )} {lines.map((l, i) => ( <span key={i}> {l.kind === 'user' ? ( <span className="text-[#89b4fa]">› {l.text}{'\n'}</span> ) : ( <span className="text-[#a6e3a1]">▎ {l.text}{'\n'}</span> )} </span> ))} </pre> <div className="border-t border-ak-border bg-ak-surface px-3 py-1.5 font-mono text-[10px] text-ak-graphite"> messages: {state.messages.length} · controller drives both react + ink renderers </div> </div> </div> )}Basic chat
Streaming chat with a mock adapter. Zero config, runs in-browser.
streamingchatTool use
Tool-calling agent that browses a mocked product catalog.
toolschatRAG
Retrieval-augmented chat with inline source citations.
ragchatCode assistant
Code-aware chat with syntax-highlighted output.
codechatMarkdown chat
Rich Markdown rendering in assistant responses.
markdownchatSupport bot
Chat with escalation, memory, and confirmation gates.
supportmemorytoolsMulti-agent
Planner + worker + reviewer topology.
multi-agentMulti-model
Switch providers on the fly in a single conversation.
multi-modelchatAgent actions
Streaming UI with live tool-call visualization.
toolsstreamingshadcn/ui chat
AgentsKit styled with shadcn/ui tokens.
chatdesign-systemMaterial UI chat
AgentsKit styled with MUI components.
chatdesign-systemSandbox runner
Agent-emitted code runs isolated in E2B / WebContainer.
sandboxtoolscodeObservability trace
Live span tree with tokens, latency, cost. Exports to LangSmith / OTEL.
observabilityproductionPersistent memory
Cross-session recall with sqlite, redis, or lancedb backends.
memorypersistenceEval suite
Run regression tests, track accuracy / latency / cost in CI.
evalproductionciSlack integration
Agent posts to Slack via @agentskit/tools.
integrationstoolsSkill swap
Hot-swap personas mid-conversation: researcher, critic, planner.
skillspromptsRuntime ReAct
Standalone agent runtime — no UI required. ReAct loop with tools + memory.
runtimemulti-agentProvider fanout
Same prompt across openai, anthropic, gemini, ollama. Compare quality + cost.
adaptersmulti-modelRAG with citations
Retrieve top-k chunks with scores and inline cite refs.
ragcitations