diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index 33fd863..e827394 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -7,6 +7,14 @@ import { GitBranch, Cpu, Zap, + Terminal, + Code2, + Eye, + Package, + Link2, + Bot, + Star, + Clipboard, } from "lucide-react"; export default function HomePage() { @@ -16,12 +24,26 @@ export default function HomePage() {
+ {/* Subtle grid pattern for depth */} +
-
- - Agent Observability Platform + {/* Top badges row */} +
+
+ + Agent Observability Platform +
+ + + Open Source +

@@ -30,16 +52,31 @@ export default function HomePage() {

-

+

See why your AI agents make the decisions they make.
Complete observability for multi-agent systems.

+ {/* pip install snippet */} +
+ {/* How it Works Section */} +
+
+
+
+
+ + Quick Setup +
+

+ Up and running in 3 steps +

+

+ Go from zero to full agent observability in under five minutes +

+
+ +
+ {/* Step 1: Install */} +
+
+ + 1 + +
+
+ +
+

Install

+

+ One command to add AgentLens to your project. +

+
+ pip install vectry-agentlens +
+
+ + {/* Step 2: Instrument */} +
+
+ + 2 + +
+
+ +
+

Instrument

+

+ Add the @trace decorator or use wrap_openai(). +

+
+ @trace + / + wrap_openai() +
+
+ + {/* Step 3: Observe */} +
+
+ + 3 + +
+
+ +
+

Observe

+

+ See every decision in the real-time dashboard. +

+
+ agentlens.vectry.tech +
+
+
+ + {/* Connecting arrows decoration */} +
+
+
+ +
+ +
+
+
+
+
+ {/* Code Example Section */}
-
-
+
+
Python SDK @@ -136,44 +264,210 @@ export default function HomePage() {
- {/* Code Block */} -
-
-
-
-
-
+ {/* Code Blocks - Two patterns stacked */} +
+ {/* Decorator Pattern */} +
+
+
+
+
+
+
+
+ decorator_pattern.py +
+ + @trace +
- example.py +
+                  
+                    from{" "}
+                    agentlens{" "}
+                    import{" "}
+                    init
+                    ,{" "}
+                    trace
+                    {"\n"}
+                    {"\n"}
+                    # Initialize AgentLens
+                    {"\n"}
+                    init
+                    (
+                    {"\n"}
+                    {"    "}
+                    api_key
+                    =
+                    "your-api-key"
+                    ,
+                    {"\n"}
+                    {"    "}
+                    endpoint
+                    =
+                    "https://agentlens.vectry.tech"
+                    {"\n"}
+                    )
+                    {"\n"}
+                    {"\n"}
+                    # Trace your agent function
+                    {"\n"}
+                    @trace
+                    (
+                    name
+                    =
+                    "research-agent"
+                    )
+                    {"\n"}
+                    async{" "}
+                    def{" "}
+                    research
+                    (
+                    topic
+                    :{" "}
+                    str
+                    ):
+                    {"\n"}
+                    {"    "}
+                    # Your agent logic here
+                    {"\n"}
+                    {"    "}
+                    return{" "}
+                    f"Researching: {"{topic}"}"
+                  
+                
-
-                
-                  from agentlens import init, trace
-                  
-
- # Initialize AgentLens -
- init( -
-     api_key="your-api-key", -
-     endpoint="https://agentlens.vectry.tech" -
- ) -
-
- # Trace your agent function -
- @trace(name="research-agent") -
- async def research(topic: str): -
-     # Your agent logic here -
-     return f"Researching: {"{topic"}" -
-
+ {/* OpenAI Wrapper Pattern */} +
+
+
+
+
+
+
+
+ openai_wrapper.py +
+ + wrap_openai + +
+
+                  
+                    from{" "}
+                    agentlens.integrations.openai{" "}
+                    import{" "}
+                    wrap_openai
+                    {"\n"}
+                    import{" "}
+                    openai
+                    {"\n"}
+                    {"\n"}
+                    # Wrap the OpenAI client
+                    {"\n"}
+                    client{" "}
+                    ={" "}
+                    openai.
+                    OpenAI
+                    ()
+                    {"\n"}
+                    client{" "}
+                    ={" "}
+                    wrap_openai
+                    (client)
+                    {"\n"}
+                    {"\n"}
+                    # Use as normal - traces automatically
+                    {"\n"}
+                    response{" "}
+                    ={" "}
+                    client.chat.completions.
+                    create
+                    (
+                    {"\n"}
+                    {"    "}
+                    model
+                    =
+                    "gpt-4"
+                    ,
+                    {"\n"}
+                    {"    "}
+                    messages
+                    =
+                    [
+                    {"{"}
+                    "role"
+                    :{" "}
+                    "user"
+                    ,{" "}
+                    "content"
+                    :{" "}
+                    "Hello!"
+                    {"}"}
+                    ]
+                    {"\n"}
+                    )
+                  
+                
+
+
+
+
+
+ + {/* Integrations Section */} +
+
+
+
+
+ + Integrations +
+

+ Works with your stack +

+

+ First-class support for the most popular AI frameworks. Drop in and start tracing. +

+
+ +
+ {/* OpenAI */} +
+
+ +
+

OpenAI

+

GPT-4, GPT-3.5, o1

+ + wrap_openai() + +
+ + {/* LangChain */} +
+
+ +
+

LangChain

+

Chains, Agents, Tools

+ + Auto-instrumented + +
+ + {/* Custom Agents */} +
+
+ +
+

Custom Agents

+

Any Python agent

+ + @trace decorator +
@@ -203,7 +497,7 @@ export default function HomePage() {
- MIT License © 2026 Vectry + MIT License © 2026 Vectry
diff --git a/packages/sdk-python/.gitignore b/packages/sdk-python/.gitignore new file mode 100644 index 0000000..849ddff --- /dev/null +++ b/packages/sdk-python/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/packages/sdk-python/README.md b/packages/sdk-python/README.md index e0b79f2..d8299e8 100644 --- a/packages/sdk-python/README.md +++ b/packages/sdk-python/README.md @@ -1,38 +1,284 @@ # AgentLens Python SDK -AgentLens provides observability for AI agents by tracing decisions, not just API calls. +[![PyPI version](https://img.shields.io/pypi/v/vectry-agentlens)](https://pypi.org/project/vectry-agentlens/) +[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/downloads/) +[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) -## Installation +Agent observability that traces **decisions**, not just API calls. -```bash -pip install agentlens -``` +## What is AgentLens? + +AgentLens is an observability SDK for AI agents. Unlike generic LLM tracing tools that only capture request/response pairs, AgentLens captures the **decision points** your agent makes: which tool it chose, what alternatives it considered, and why. This gives you a decision tree view of agent behavior, not just a flat log of API calls. ## Quick Start -```python -from agentlens import init, trace - -# Initialize AgentLens -init(api_key="your-api-key", endpoint="https://agentlens.vectry.tech") - -# Trace your agent functions -@trace(name="research-agent") -async def research(topic: str) -> str: - return f"Researching: {topic}" +```bash +pip install vectry-agentlens ``` -## Features +```python +import agentlens -- **Decision Tracing**: Log and visualize agent decisions with alternatives -- **Context Awareness**: Monitor context window utilization -- **Cost Intelligence**: Track token usage and costs per operation -- **Integrations**: Native support for LangChain and OpenAI +# Initialize once at startup +agentlens.init(api_key="your-api-key") -## Documentation +# Trace any function with a decorator +@agentlens.trace(name="research-agent", tags=["research"]) +def research(topic: str) -> str: + # Your agent logic here + return f"Results for: {topic}" -Full documentation available at [https://agentlens.vectry.tech/docs](https://agentlens.vectry.tech/docs) +research("quantum computing") +``` + +The `@trace` decorator works with both sync and async functions. Traces are batched and sent to the AgentLens API automatically. + +You can also use `trace` as a context manager: + +```python +with agentlens.trace(name="my-operation", session_id="user-123"): + # Everything inside is traced + result = do_work() +``` + +## Integrations + +### OpenAI + +Auto-capture every `chat.completions.create` call with token counts, cost estimation, and tool-call decisions. + +```bash +pip install vectry-agentlens[openai] +``` + +```python +import openai +import agentlens +from agentlens.integrations.openai import wrap_openai + +agentlens.init(api_key="your-api-key") + +client = openai.OpenAI() +client = wrap_openai(client) + +# All calls are now traced automatically +@agentlens.trace(name="assistant") +def ask(question: str) -> str: + response = client.chat.completions.create( + model="gpt-4o", + messages=[{"role": "user", "content": question}], + ) + return response.choices[0].message.content + +ask("What is the capital of France?") +``` + +`wrap_openai` instruments the client in-place. For each call it creates an LLM span with: +- Model name, temperature, and max_tokens +- Token usage (prompt, completion, total) +- Estimated cost in USD (built-in pricing for GPT-4, GPT-4o, GPT-3.5-turbo variants) +- Automatic `TOOL_SELECTION` decision points when the model invokes function/tool calls + +Streaming is also supported transparently. + +### LangChain + +Drop in a callback handler to trace chains, agents, LLM calls, and tool invocations. + +```bash +pip install vectry-agentlens[langchain] +``` + +```python +import agentlens +from agentlens.integrations.langchain import AgentLensCallbackHandler + +agentlens.init(api_key="your-api-key") + +handler = AgentLensCallbackHandler( + trace_name="langchain-agent", + tags=["production"], + session_id="user-456", +) + +# Pass the handler to any LangChain chain or agent +result = chain.invoke( + {"input": "Summarize this document"}, + config={"callbacks": [handler]}, +) +``` + +The handler automatically creates spans for LLM calls, tool calls, and chain execution. Agent tool selections are logged as `TOOL_SELECTION` decision points. + +It also works inside an existing trace context: + +```python +@agentlens.trace(name="my-pipeline") +def run_pipeline(query: str): + handler = AgentLensCallbackHandler() + return chain.invoke({"input": query}, config={"callbacks": [handler]}) +``` + +### Custom Agents + +For any agent framework (or your own), use `log_decision()` to record decision points manually. + +```python +import agentlens +from agentlens import log_decision + +agentlens.init(api_key="your-api-key") + +@agentlens.trace(name="routing-agent") +def route_request(query: str) -> str: + # Your routing logic + chosen_agent = "research-agent" + + log_decision( + type="ROUTING", + chosen={"name": chosen_agent, "confidence": 0.92}, + alternatives=[ + {"name": "support-agent", "confidence": 0.45, "reason_rejected": "not a support query"}, + {"name": "sales-agent", "confidence": 0.12, "reason_rejected": "no purchase intent"}, + ], + reasoning="Query contains research keywords", + context_snapshot={"tokens_used": 1200, "tokens_available": 6800}, + cost_usd=0.003, + duration_ms=45, + ) + + return dispatch(chosen_agent, query) +``` + +Decision types include: `TOOL_SELECTION`, `ROUTING`, `RETRY`, `ESCALATION`, `MEMORY_RETRIEVAL`, `PLANNING`, and `CUSTOM`. + +## API Reference + +### `agentlens.init()` + +Initialize the SDK. Call once at application startup. + +```python +agentlens.init( + api_key="your-api-key", # Required. Your AgentLens API key. + endpoint="https://...", # API endpoint (default: https://agentlens.vectry.tech) + flush_interval=5.0, # Seconds between batch flushes (default: 5.0) + max_batch_size=10, # Traces per batch before auto-flush (default: 10) + enabled=True, # Set False to disable sending (e.g., in tests) +) +``` + +### `agentlens.trace()` + +Decorator or context manager that creates a trace (or a nested span if already inside a trace). + +```python +# As decorator +@agentlens.trace(name="my-agent", tags=["v2"], session_id="user-789", metadata={"env": "prod"}) +def my_agent(): + ... + +# As context manager +with agentlens.trace(name="sub-task") as ctx: + ... +``` + +| Parameter | Type | Description | +|-------------|------------------|--------------------------------------| +| `name` | `str` | Name for the trace or span | +| `tags` | `list[str]` | Tags for filtering in the dashboard | +| `session_id`| `str` | Group traces by user session | +| `metadata` | `dict` | Arbitrary key-value metadata | + +### `agentlens.log_decision()` + +Record a decision point inside an active trace. + +```python +agentlens.log_decision( + type="TOOL_SELECTION", + chosen={"name": "search", "confidence": 0.95}, + alternatives=[{"name": "calculator", "confidence": 0.3}], + reasoning="User asked a factual question", + context_snapshot={"tokens_used": 500}, + cost_usd=0.001, + duration_ms=23, +) +``` + +| Parameter | Type | Description | +|-------------------|--------------|------------------------------------------------| +| `type` | `str` | Decision type (see types above) | +| `chosen` | `dict` | The selected option (`name`, `confidence`, etc.) | +| `alternatives` | `list[dict]` | Rejected options with reasons | +| `reasoning` | `str` | Why this option was chosen | +| `context_snapshot`| `dict` | State at decision time (tokens, memory, etc.) | +| `cost_usd` | `float` | Cost of this decision in USD | +| `duration_ms` | `int` | Time taken to make the decision | + +### `wrap_openai()` + +Instrument an OpenAI client for automatic tracing. + +```python +from agentlens.integrations.openai import wrap_openai + +client = wrap_openai(openai.OpenAI()) +``` + +Returns the same client instance with `chat.completions.create` wrapped. All calls automatically generate LLM spans and tool-call decision points. + +### `AgentLensCallbackHandler` + +LangChain callback handler for automatic tracing. + +```python +from agentlens.integrations.langchain import AgentLensCallbackHandler + +handler = AgentLensCallbackHandler( + trace_name="my-chain", # Trace name (if no active trace exists) + tags=["prod"], # Optional tags + session_id="user-123", # Optional session ID +) +``` + +## Architecture + +``` +Your Agent Code + │ + ▼ +AgentLens SDK ── @trace, log_decision(), wrap_openai() + │ + ▼ +Batched HTTP Transport ── Collects traces, flushes every 5s or 10 traces + │ + ▼ +AgentLens API ── https://agentlens.vectry.tech/api/traces + │ + ▼ +Dashboard ── Decision trees, analytics, real-time streaming +``` + +The SDK is lightweight and non-blocking. Traces are serialized and batched in a background thread, so your agent code is never slowed down by observability. + +## Dashboard + +View your traces at [agentlens.vectry.tech](https://agentlens.vectry.tech): + +- **Decision Trees** - Visualize the full decision path of every agent run +- **Analytics** - Token usage, cost breakdowns, latency percentiles +- **Real-time Streaming** - Watch agent decisions as they happen +- **Session Grouping** - Track multi-turn conversations by session ID + +## Development + +```bash +cd packages/sdk-python +pip install -e ".[all]" # installs openai + langchain extras +python -m pytest tests/ -v +``` ## License -MIT © 2026 Vectry +MIT - Built by [Vectry](https://vectry.tech) diff --git a/packages/sdk-python/pyproject.toml b/packages/sdk-python/pyproject.toml index a4a353e..97283bb 100644 --- a/packages/sdk-python/pyproject.toml +++ b/packages/sdk-python/pyproject.toml @@ -1,9 +1,9 @@ [build-system] requires = ["hatchling"] -build-backend = "hatchling.backends" +build-backend = "hatchling.build" [project] -name = "agentlens" +name = "vectry-agentlens" version = "0.1.0" description = "Agent observability that traces decisions, not just API calls" readme = "README.md" @@ -25,7 +25,10 @@ dependencies = [ [project.optional-dependencies] langchain = ["langchain-core>=0.1.0"] openai = ["openai>=1.0.0"] -all = ["agentlens[langchain,openai]"] +all = ["vectry-agentlens[langchain,openai]"] + +[tool.hatch.build.targets.wheel] +packages = ["agentlens"] [project.urls] Homepage = "https://agentlens.vectry.tech"