Core Concepts
Reasoning
Memory & Retrieval
Agent Types
Design Patterns
Training & Alignment
Frameworks
Tools
Safety & Security
Evaluation
Meta
Core Concepts
Reasoning
Memory & Retrieval
Agent Types
Design Patterns
Training & Alignment
Frameworks
Tools
Safety & Security
Evaluation
Meta
This is an old revision of the document!
Chainlit is an open-source Python framework for building production-ready conversational AI applications1). With over 12,000 stars on GitHub, it lets developers go from a Python script to a polished chat interface in minutes — with real-time streaming, step-by-step observability, file uploads, authentication, and integrations with LangChain, LlamaIndex, and OpenAI.
Chainlit focuses on the gap between AI backend logic and user-facing interfaces, providing an event-driven architecture with Python decorators that eliminates the need for frontend development expertise while delivering a professional chat experience2).
Chainlit uses an event-driven architecture with Python decorators for chat lifecycle hooks. The core decorators — @cl.on_chat_start and @cl.on_message — handle session initialization and message processing. The framework automatically renders a web-based chat UI with streaming support, message history, and step visualization.
A key feature is Chain of Thought observability: Chainlit visualizes intermediate AI steps (retrieval, reasoning, tool calls) in the UI, giving users transparency into how the AI reached its answer. This builds trust and aids debugging.
# Install Chainlit # pip install chainlit import chainlit as cl from openai import AsyncOpenAI client = AsyncOpenAI() @cl.on_chat_start async def start(): cl.user_session.set("history", []) await cl.Message(content="Hello! How can I help you today?").send() @cl.on_message async def main(message: cl.Message): history = cl.user_session.get("history") history.append({"role": "user", "content": message.content}) msg = cl.Message(content="") await msg.send() # Stream response from OpenAI stream = await client.chat.completions.create( model="gpt-4o", messages=history, stream=True ) async for chunk in stream: if chunk.choices[0].delta.content: await msg.stream_token(chunk.choices[0].delta.content) history.append({"role": "assistant", "content": msg.content}) cl.user_session.set("history", history) await msg.update() # Run with: chainlit run app.py # LangChain integration example from langchain_openai import ChatOpenAI from langchain.chains import LLMChain from langchain.prompts import PromptTemplate @cl.on_message async def langchain_handler(message: cl.Message): llm = ChatOpenAI(model="gpt-4o", streaming=True) prompt = PromptTemplate.from_template("Answer: {question}") chain = LLMChain(llm=llm, prompt=prompt) cb = cl.AsyncLangchainCallbackHandler() result = await chain.acall( message.content, callbacks=[cb] ) await cl.Message(content=result["text"]).send()
%%{init: {'theme': 'dark'}}%%
graph TB
User([User]) -->|Chat Message| WebUI[Chainlit Web UI]
WebUI -->|WebSocket| Server[Chainlit Server]
Server -->|@cl.on_chat_start| Init[Session Init]
Server -->|@cl.on_message| Handler[Message Handler]
Handler -->|API Call| LLM[LLM Provider]
LLM -->|Stream Tokens| Handler
Handler -->|cl.Message| WebUI
Init -->|cl.user_session| Session[Session Store]
Handler -->|Steps| COT[Chain of Thought]
COT -->|Visualization| WebUI
Handler -->|Callbacks| LC[LangChain]
Handler -->|Callbacks| LI[LlamaIndex]
Handler -->|MCP| Tools[External Tools]
Config[config.toml] -->|Theme + Auth| Server
| Feature | Chainlit | Streamlit | Gradio | Flask/FastAPI |
|---|---|---|---|---|
| Time to chat UI | Minutes | Hours | Hours | Days |
| AI observability | Built-in | None | None | None |
| Streaming | Native | Limited | Limited | Manual |
| Frontend needed | No | No | No | Yes |
| Session management | Built-in | Basic | Basic | Manual |