Skip to main content

Open source Python library for multi-agent web interfaces.

Project description

GenAILit

GenAILit is a small Python library for building web interfaces for multi-agent systems. It gives you a single-process, single-port runtime with FastAPI, WebSocket streaming, and an embedded DebugPanel for LLMOps-style inspection.

What it is

GenAILit is not just a chat UI. It is a lightweight runtime and adapter layer for agentic applications where you want to:

  • expose an agent over the web from pure Python
  • stream events and tokens over WebSocket
  • inspect execution traces and metrics
  • stay compatible with SageMaker Studio and other proxy-based environments

Why it is not only a chat UI

A chat UI only renders messages. GenAILit also gives you:

  • a framework-agnostic event model
  • telemetry for tokens, latency, provider, model, cost, errors, and retries
  • adapters for different backends
  • a built-in debug surface for tracing multi-agent execution

That makes it useful for building and auditing multi-agent systems, not only for chatting with them.

Installation

pip install genailit

Optional LangGraph support:

pip install "genailit[langgraph]"

Requirements:

  • Python 3.10+
  • pydantic>=2
  • fastapi>=0.110
  • uvicorn[standard]>=0.27

Quickstart

The simplest way to build an app is with @app.agent:

from genailit import GenAILitApp

app = GenAILitApp()


@app.agent
async def demo(input_data, context):
    yield "Hola "
    yield "desde "
    yield "GenAILit"


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8501)

Run it with the CLI:

genailit run app.py --host 0.0.0.0 --port 8501

The UI opens a WebSocket to the same host and port, so it works well behind SageMaker and similar proxies.

Using LangGraph

LangGraph is optional and stays outside the core runtime. Install the extra first:

pip install "genailit[langgraph]"

Then use the adapter:

from genailit import GenAILitApp
from genailit.adapters.langgraph import LangGraphAdapter

graph = ...
adapter = LangGraphAdapter(graph)
app = GenAILitApp(adapter=adapter)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8501)

See examples/langgraph_demo.py for a minimal runnable example.

Examples

Architecture

GenAILit is intentionally split into small pieces:

  • core - the FastAPI runtime and WebSocket server
  • adapters - bridge layers for agent backends
  • events - the framework-agnostic GenAILitEvent contract
  • telemetry - in-memory session traces and metrics
  • metrics - session/agent usage data structures and console rendering
  • DebugPanel - the built-in execution inspector

The core stays agnostic. Adapters translate backend-specific behavior into GenAILit events.

Event catalog

Every streamed item uses the same shape:

GenAILitEvent(name="event.name", payload={...})

Canonical event names for 0.1.x:

Event Recommended payload
session.started {"session_id": str, "run_id": str | None}
session.ended {"session_id": str, "run_id": str | None}
agent.token {"delta": str}. Legacy {"token": str} is still accepted by the UI and telemetry.
agent.message {"content": str}. Legacy {"message": str} is still accepted.
node.started {"name": str} or {"session_id": str, "run_id": str | None} for root execution nodes.
node.ended {"name": str} or {"run_id": str | None} for root execution nodes.
tool.started {"name": str} or {"tool_name": str}.
tool.ended {"name": str} or {"tool_name": str}.
llm.started {"provider": str, "model": str, "metadata": {"source": str}, "timing": {"latency_ms": None, "ttft_ms": None}}.
llm.ended {"provider": str, "model": str, "usage": {...}, "metadata": {"source": str}, "timing": {...}}.
metrics.updated {"usage": {"input_tokens": int, "output_tokens": int, "total_tokens": int}, "provider": str, "model": str, "timing": {"latency_ms": float, "ttft_ms": float | None}, "cost": {"cost_usd": float}}.
error {"message": str, "type": str}.

Payloads may include fewer fields when the backend cannot provide them. Raw backend payloads are not included unless an adapter explicitly enables include_raw. Any event may also include payload.agent_id (or agent, agent_name, node_id, node) to attribute its usage to a specific agent in multi-agent flows; see Per-agent breakdown.

SageMaker Studio

GenAILit is designed to work in SageMaker Studio with:

  • single-process execution
  • single-port serving
  • no Node or Vite runtime
  • host 0.0.0.0
  • port 8501

That keeps the app simple to install with pip and avoids frontend build steps in runtime.

Telemetry and LLMOps

GenAILit tracks observability data such as:

  • input tokens
  • output tokens
  • total tokens
  • provider
  • model
  • latency
  • TTFT
  • cost
  • error count
  • retry count

The DebugPanel surfaces those metrics alongside execution events and a basic execution tree. When real usage metadata is available, GenAILit prefers it over token estimates.

TelemetryStore.get_session_metrics(session_id) returns:

{
    "total_events": int,
    "input_tokens": int,
    "output_tokens": int,
    "total_tokens": int,
    "model": str | None,
    "provider": str | None,
    "latency_ms": float | None,
    "ttft_ms": float | None,
    "cost_usd": float | None,
    "error_count": int,
    "retry_count": int,
    "estimated": {"tokens": bool, "cost": bool},
}

Telemetry precedence:

  1. Real usage wins: payload.usage.input_tokens, payload.usage.output_tokens, and payload.usage.total_tokens.
  2. Legacy aliases are used next: prompt_tokens, completion_tokens, tokens_in, and tokens_out.
  3. If no token metadata exists, output tokens are estimated from agent.token or agent.message text.

Per-agent breakdown

Multi-agent flows can attribute usage to the agent that produced it by including payload.agent_id (or agent, agent_name, node_id, node as aliases) on the events emitted for that agent. TelemetryStore.get_session_report(session_id) returns a SessionReport:

from genailit import SessionReport, render_session_report

report: SessionReport = app.telemetry.get_session_report(session_id)
print(render_session_report(report))
Session

Input Tokens          80
Visible Output        234
Reasoning             135
Total                 449
Cost                  $0.012

Agents

Planner
Model: GPT-5
Input: 10
Output: 40
Reasoning: 30
Cost: $0.001

Researcher
Model: Claude Sonnet
Input: 50
Output: 120
Reasoning: 90
Cost: $0.007

Writer
Model: Gemini Flash
Input: 20
Output: 74
Reasoning: 15
Cost: $0.004

SessionReport.usage is a TokenUsage (input_tokens, output_tokens, reasoning_tokens, cost_usd, and a computed total_tokens property), and SessionReport.agents is a tuple of AgentMetrics, one per distinct agent_id seen in the session, in first-seen order. When at least one agent is identified, session totals are the sum of every agent's usage (each agent typically issues its own LLM call). Sessions with no agent_id at all fall back to the single-flow usage used by get_session_metrics.

Provider and model are resolved from payload.provider, payload.model, payload.metadata.ls_provider, payload.metadata.ls_model_name, and payload.response_metadata.model_name. Cost is never estimated; cost_usd is only populated from explicit payload.cost.cost_usd or payload.cost_usd. Latency and TTFT prefer explicit payload.timing values and otherwise fall back to in-memory session timestamps.

Public API stability

For 0.1.x, the stable surface is:

  • GenAILitEvent(name, payload)
  • GenAILitApp(adapter=None), @app.agent, app.asgi_app, and app.run(...)
  • AdapterContext and BaseAgentAdapter.stream(input_data, context)
  • TelemetryStore.record, extend, snapshot, clear, get_session_trace, get_session_metrics, and get_session_report
  • TokenUsage, AgentMetrics, SessionReport, and render_session_report(report) / print_session_report(report)
  • LangGraphAdapter(graph, input_key="messages", stream_mode=None, include_raw=False)
  • genailit run app.py --host 0.0.0.0 --port 8501

Privacy defaults

GenAILit avoids storing sensitive content by default:

  • raw payloads are not persisted unless explicitly requested
  • prompts are not stored in new telemetry structures by default
  • message bodies and token text are only shown where needed for the live UI

This keeps the default footprint small while still supporting inspection when you enable it.

Status

GenAILit is experimental. The public API may change as the library grows. The current goal is to keep the runtime small, stable in SageMaker, and easy to reason about.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

genailit-0.2.0.tar.gz (408.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

genailit-0.2.0-py3-none-any.whl (65.3 kB view details)

Uploaded Python 3

File details

Details for the file genailit-0.2.0.tar.gz.

File metadata

  • Download URL: genailit-0.2.0.tar.gz
  • Upload date:
  • Size: 408.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for genailit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 766bff7ddf340775e327ab70cab634e485dd04fffa51bb6ac6832ca504b75bf4
MD5 e758dd07c07271a5bab423d3cfdce171
BLAKE2b-256 290e8cd753fed564519c8ac8222ff85db2d439c62101602e3a165326797e65cb

See more details on using hashes here.

File details

Details for the file genailit-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: genailit-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 65.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for genailit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d72203e249e656f78462b94b09903d5a61c48bed88b1714315d5301cc4462132
MD5 fcf195fd064a7bfc19d0254c140f96de
BLAKE2b-256 51bc2134b7f6b1b7d3006519acfe9286159782fd44d618430659c33fa8acf370

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page