FastAPI Integration
The FastAPI middleware automatically extracts session IDs from incoming HTTP request headers and sets them in the BeliefState session context. This means your endpoint handlers don't need to manually call tracker.set_session() — the middleware does it transparently for every request.
Middleware Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
app | ASGIApp | (required) | The ASGI application instance (FastAPI app). Passed automatically by FastAPI's add_middleware(). |
header_name | str | "X-Session-ID" | HTTP header name to extract the session ID from. The middleware reads this header from every incoming request. If the header is missing, the session defaults to "default". |
pythonfrom fastapi import FastAPI, Depends
from beliefstate import FastAPIBeliefTrackerMiddleware, get_session_id
app = FastAPI()
# Option 1: Middleware (sets session context automatically)
app.add_middleware(
FastAPIBeliefTrackerMiddleware,
header_name="X-Session-ID"
)
# Option 2: Dependency injection
@app.post("/chat")
async def chat(message: str, session_id: str = Depends(get_session_id)):
# session_id is extracted from X-Session-ID header
# session context is automatically set
response = await chat_with_llm(message)
return {"response": response}
ℹ️ Context Propagation Mechanics: Web frameworks process multiple requests concurrently on different asynchronous task contexts. BeliefState uses Python's standard contextvars.ContextVar (session_context) to store and isolate session identifiers.
When a request comes in:
- The ASGI middleware intercepts the request headers and extracts the session key.
- It sets the value via
token = session_context.set(session_id), propagating the variable down the active execution flow. - When the request handler finishes, the middleware executes a
finallyblock to callsession_context.reset(token), ensuring zero context leakage across different requests.
Testing Locally
Send requests with the session header to test the integration:
bash# Set session via header
curl -X POST http://localhost:8000/chat \
-H "X-Session-ID: user_123" \
-H "Content-Type: application/json" \
-d '{"message": "I live in Tokyo"}'
Flask Integration
For Flask applications, BeliefState provides both a WSGI middleware wrapper and Flask request hooks. The WSGI middleware wraps Flask's wsgi_app and extracts session IDs from request headers, while the hooks integrate with Flask's request lifecycle.
Middleware Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
app | WSGIApp | (required) | The WSGI application instance (Flask's wsgi_app). |
header_name | str | "X-Session-ID" | HTTP header name to extract the session ID from. |
Hook Registration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
app | Flask | (required) | The Flask application instance. |
header_name | str | "X-Session-ID" | HTTP header name to extract the session ID from. Registered as a before_request hook. |
pythonfrom flask import Flask
from beliefstate import FlaskBeliefTrackerMiddleware, register_flask_hooks
app = Flask(__name__)
# WSGI middleware for context propagation
app.wsgi_app = FlaskBeliefTrackerMiddleware(app.wsgi_app, header_name="X-Session-ID")
# Flask request hooks (alternative or additional)
register_flask_hooks(app, header_name="X-Session-ID")
ℹ️ Middleware vs. Hooks: The WSGI middleware intercepts requests at the WSGI layer (before Flask processes them), while hooks use Flask's before_request / teardown_request lifecycle. Either approach works — the middleware is recommended for consistency with other frameworks.
Generic ASGI Middleware
The ASGI middleware works with any ASGI-compatible framework: Starlette, Litestar, Quart, or any custom ASGI application. It's the same middleware used internally by the FastAPI integration.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
app | ASGIApp | (required) | The ASGI application instance. |
header_name | str | "X-Session-ID" | HTTP header name to extract the session ID from. Case-insensitive (per HTTP spec). |
pythonfrom starlette.applications import Starlette
from beliefstate import BeliefTrackerASGIMiddleware
app = Starlette()
app.add_middleware(BeliefTrackerASGIMiddleware, header_name="X-Session-ID")
# Works with any ASGI framework: Starlette, Litestar, Quart, etc.
LangChain Callback
The LangChain callback handler integrates with LangChain's callback system. It intercepts the on_llm_end lifecycle event, capturing the prompt and response text, then dispatches a background belief tracking task. Attach it to any LangChain chain, agent, or LLM invocation.
Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
tracker | BeliefTracker | (required) | The BeliefTracker instance to use for belief extraction. Must be initialized with an adapter and config before passing. |
pythonfrom beliefstate import session_context, BeliefTrackerLangchainCallback
# Set session context before invoking the chain
session_context.set("user_123")
# Attach callback handler to your chain
handler = BeliefTrackerLangchainCallback(tracker=tracker)
await llm.ainvoke("Hello!", config={"callbacks": [handler]})
ℹ️ Important: You must set session_context before invoking the chain, since LangChain callbacks don't have access to HTTP headers. Use session_context.set("user_123") or wrap calls inside a middleware that sets the context.
LlamaIndex Callback
The LlamaIndex callback integrates with LlamaIndex's callback manager system. It captures LLM events via on_event_end and dispatches tracking tasks. Register it in the global Settings.callback_manager to automatically track all LLM calls.
Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
tracker | BeliefTracker | (required) | The BeliefTracker instance to use for belief extraction. |
pythonfrom llama_index.core import Settings
from llama_index.core.callbacks import CallbackManager
from beliefstate import LlamaIndexBeliefTrackerCallback
callback = LlamaIndexBeliefTrackerCallback(tracker=tracker)
Settings.callback_manager = CallbackManager([callback])
OpenAI Assistants Observer
The Assistants observer watches an OpenAI Assistant run and extracts beliefs from the thread messages once the run completes. Unlike the @tracker.wrap pattern, this observer polls the run status and processes the full thread conversation in bulk.
Function Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
tracker | BeliefTracker | (required) | The BeliefTracker instance. |
client | AsyncOpenAI | (required) | The OpenAI async client used to poll the run status and retrieve thread messages. |
thread_id | str | (required) | The OpenAI thread ID containing the conversation messages. |
run_id | str | (required) | The run ID to observe. The observer waits for this run to complete before extracting beliefs. |
session_id | str | (required) | Session ID to associate extracted beliefs with. Maps to a user or conversation in your belief store. |
pythonimport asyncio
from beliefstate import observe_run
# Observe assistant run and extract beliefs from thread messages
asyncio.create_task(
observe_run(
tracker=tracker,
client=openai_client,
thread_id=thread_id,
run_id=run.id,
session_id="session_123"
)
)
ℹ️ Callback Hook Lifecycles: The LangChain and LlamaIndex callback handlers inherit from their respective framework lifecycle hooks (e.g. on_llm_end or on_event_end).
When the model finishes generating a response:
- The callback intercepts the output response text and input prompt history.
- It grabs the active
session_idandconversation_idfrom thread context variables. - It packages this payload and schedules a background belief tracking task asynchronously via the tracker dispatcher, keeping the application response pipeline completely non-blocking.
Error Handling in Integrations
All integrations are designed to be fail-safe. If any part of the belief tracking pipeline fails (adapter error, store error, parsing error), the failure is logged as a warning but never propagates to your application. Your users always receive their LLM response, even if background tracking encounters an error.