Chat Component - Reference Guide
Read this before creating chat widgets.
Overview
The chat component provides a full-featured conversational UI with:
- Message rendering with inline markdown
- Streaming responses with token-by-token display
- Stop-generation (cancel in-flight LLM responses)
- Thread management (create, switch, delete)
- Slash command palette (type
/to see commands) - Settings panel (model, temperature, system prompt)
- LLM provider adapters (OpenAI, Anthropic, custom callback)
Quick Start
Via MCP Tool
{
"name": "create_chat_widget",
"arguments": {
"title": "AI Assistant",
"model": "gpt-4",
"system_prompt": "You are a helpful assistant.",
"streaming": true,
"provider": "openai"
}
}
Via Python
from pywry import App
from pywry.chat import ChatConfig, ChatWidgetConfig
app = App()
config = ChatWidgetConfig(
title="AI Chat",
height=600,
chat=ChatConfig(
system_prompt="You are helpful.",
model="gpt-4",
streaming=True,
provider="openai",
),
)
# Widget creation handled by MCP or directly via app.show()
MCP Tools
create_chat_widget
Creates a chat widget. Returns {widget_id, thread_id}.
| Parameter | Type | Default | Description | |----------------|---------|----------|--------------------------------| | title | string | "Chat" | Window title | | height | integer | 600 | Window height | | system_prompt | string | "" | System prompt for LLM | | model | string | "gpt-4" | Model name | | temperature | number | 0.7 | Sampling temperature (0-2) | | max_tokens | integer | 4096 | Max tokens per response | | streaming | boolean | true | Enable streaming | | persist | boolean | false | Persist threads in ChatStore | | provider | string | — | "openai", "anthropic", "callback" | | show_sidebar | boolean | true | Show thread sidebar | | slash_commands | array | — | Custom slash commands |
chat_send_message
Send a user message. Returns {message_id, thread_id, sent}.
chat_stop_generation
Stop an in-flight generation. Idempotent. Returns partial content.
chat_manage_thread
Thread CRUD: create, switch, delete, rename, list.
chat_register_command
Register a slash command at runtime.
chat_get_history
Paginated conversation history with cursor (before_id).
chat_update_settings
Update model, temperature, system prompt, etc.
chat_set_typing
Show/hide the typing indicator.
Event Contract
Incoming Events (Python → Frontend)
| Event | Payload | |---------------------------|--------------------------------------------| | chat:assistant-message | {messageId, text, threadId} | | chat:stream-chunk | {chunk, messageId, threadId, done} | | chat:typing-indicator | {typing, threadId} | | chat:switch-thread | {threadId} | | chat:update-thread-list | {threads: [{thread_id, title}]} | | chat:clear | {} | | chat:register-command | {name, description} | | chat:update-settings | {model, temperature, system_prompt} | | chat:state-response | {messages, threads, settings, activeThreadId} | | chat:generation-stopped | {messageId, threadId, partialContent} |
Outgoing Events (Frontend → Python)
| Event | Payload | |--------------------------|---------------------------------------------| | chat:user-message | {text, threadId, timestamp} | | chat:slash-command | {command, args, threadId} | | chat:thread-create | {title} | | chat:thread-switch | {threadId} | | chat:thread-delete | {threadId} | | chat:settings-change | {key, value} | | chat:request-history | {threadId, limit} | | chat:stop-generation | {threadId, messageId} | | chat:request-state | {} |
Stop-Generation Mechanics
- User clicks Stop button → frontend immediately re-enables UI
chat:stop-generationsent to backend- Backend sets
cancel_eventonGenerationHandle - LLM provider checks
cancel_event.is_set()between chunks - Provider raises
GenerationCancelledError→ partial content saved - Backend emits
chat:generation-stoppedwith partial content - Frontend marks message as "(stopped)"
The UI never waits for backend confirmation — recovery is instant.
Default Slash Commands
| Command | Description | |-----------|----------------------------| | /clear | Clear conversation | | /export | Export chat history | | /model | Switch model | | /system | Change system prompt |
Register custom commands via chat_register_command tool or ChatConfig.slash_commands list.
LLM Providers
OpenAI
{"provider": "openai"}
Requires openai package and OPENAI_API_KEY environment variable.
Anthropic
{"provider": "anthropic"}
Requires anthropic package and ANTHROPIC_API_KEY environment variable.
Custom Callback
from pywry.chat.providers.callback import CallbackProvider
provider = CallbackProvider(
prompt_fn=my_prompt, # (session_id, content_blocks, cancel_event) → AsyncIterator[SessionUpdate]
)
Safety Constants
| Constant | Value | Purpose | |--------------------------|----------|----------------------------------| | MAX_RENDERED_MESSAGES | 200 | DOM cap for performance | | MAX_CONTENT_LENGTH | 100,000 | Per-message content limit | | MAX_MESSAGES_PER_THREAD | 1,000 | Eviction threshold | | STREAM_TIMEOUT_SECONDS | 30 | Max silence before timeout | | SEND_COOLDOWN_MS | 1,000 | Input rate limit | | GENERATION_HANDLE_TTL | 300 | Auto-expire stale handles |