Metadata-Version: 2.4
Name: mirrorkit
Version: 0.2.4
Summary: Mirrors client: a drop-in production trace collector for LLM agents, plus the `mirrors` CLI (install `mirrorkit[cli]`).
Author: Mirrors
License: MIT
Project-URL: Homepage, https://mirror.dev
Keywords: llm,tracing,observability,langchain,anthropic,openai,cli
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: cli
Requires-Dist: click>=8.1; extra == "cli"
Requires-Dist: httpx>=0.27; extra == "cli"
Requires-Dist: pydantic>=2.7; extra == "cli"
Provides-Extra: langchain
Requires-Dist: langchain-core; extra == "langchain"
Provides-Extra: anthropic
Requires-Dist: anthropic; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: openai; extra == "openai"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: click>=8.1; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: pydantic>=2.7; extra == "dev"
Dynamic: license-file

# mirrorkit

A lightweight, **drop-in** production trace collector for LLM agents. Add two
lines to your existing LangChain / LangGraph / Anthropic / OpenAI script and
your agent's traces start streaming to your Mirrors backend — keyed by an API
key, with negligible latency (non-blocking, background-batched).

## Install

```bash
pip install mirrorkit
```

Zero required runtime dependencies — the sender uses only the Python stdlib.
LangChain / Anthropic / OpenAI are instrumented only if they're importable.

## Usage (2 lines)

```python
import mirrorkit
mirrorkit.init(api_key="mk_live_...", project="my-agent")
```

That's it. Run your agent normally — traces are captured automatically and
shipped in the background. The endpoint defaults to the `MIRROR_ENDPOINT`
environment variable, then to the production URL.

```python
mirrorkit.init(
    api_key="mk_live_...",
    project="my-agent",
    endpoint="https://api.mirror.dev",  # optional override
    flush_interval=2.0,                  # seconds between batch flushes
    max_batch=50,                        # max traces per POST
    instrument=True,                     # auto-hook LangChain/Anthropic/OpenAI
)
```

## Manual logging

For frameworks you don't auto-instrument, enqueue a trace yourself. Messages
are OpenAI-style chat dicts:

```python
import mirrorkit
mirrorkit.init(api_key="mk_live_...", project="my-agent")

mirrorkit.log_trace(
    [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What's the weather in Paris?"},
        {
            "role": "assistant",
            "content": None,
            "tool_calls": [
                {
                    "id": "call_1",
                    "function": {"name": "get_weather", "arguments": '{"city": "Paris"}'},
                }
            ],
        },
        {"role": "tool", "tool_call_id": "call_1", "content": "18C, sunny"},
        {"role": "assistant", "content": "It's 18C and sunny in Paris."},
    ],
    trace_id="optional-id",
    model="gpt-4o",
)

mirrorkit.flush()  # also runs automatically at interpreter exit
```

## LangChain global handler

`init()` registers a global LangChain callback handler automatically, so you
don't need to pass callbacks. If your setup doesn't honor the global hook,
pass the handler explicitly:

```python
from langchain_core.runnables import RunnableConfig
import mirrorkit

mirrorkit.init(api_key="mk_live_...", project="my-agent")
chain.invoke(inputs, config=RunnableConfig(callbacks=[mirrorkit.handler()]))
```

## API

- `mirrorkit.init(api_key, project="default", endpoint=None, *, flush_interval=2.0, max_batch=50, instrument=True)`
- `mirrorkit.log_trace(messages, *, trace_id=None, model=None)`
- `mirrorkit.flush(timeout=5.0)`
- `mirrorkit.shutdown()`
- `mirrorkit.handler()` — LangChain callback handler for manual registration

## The `mirrors` CLI

The same package ships a terminal client of the hosted backend — **full parity with
the web app**: anything you can do in the UI you can do from the CLI (log in,
ingest+build a twin, explore it, run it, add business context, apply agent-suggested
fixes, author + run evals). It needs a few extra deps, so install the `cli` extra:

```bash
pip install "mirrorkit[cli]"   # adds the `mirrors` command (click + httpx + pydantic)
```

Authenticate with a workspace API key (`mk_live_…`, minted in the web app), then:

```bash
mirrors login                                  # paste the key (or --api-key / --dev)
mirrors env ls                                 # list environments
mirrors build traces.jsonl --name airline      # ingest + build a twin (streams the log)
mirrors build --project airline --name airline # build from a collector stream
mirrors env assets|schema|fidelity|drift|traces <env>   # explore the twin
mirrors query <env> "cancel my flight"         # run the twin (one-shot) + see the trace
mirrors chat <env>                             # multi-turn conversation with the twin
mirrors container status|start|stop <env>      # its hosted HTTP endpoint
mirrors context add <env> --text "…"           # business context that lifts fidelity
mirrors proposal new|accept <env> [id]         # agent-suggested changes -> rebuild
mirrors eval generate <env> --save-as smoke    # auto-author eval cases
mirrors eval create <env> --name smoke --from cases.json
mirrors eval run <eval-set-id>                 # run evals; `mirrors run show <run-id>`
mirrors usage                                  # task-minutes vs. plan allowance
```

Credentials live in `~/.mirrors/config.json` (or `MIRRORS_BASE_URL` /
`MIRRORS_API_KEY` for CI). Add `--json` to any command for machine-readable output.
The CLI talks only HTTP to the backend — it has no engine/build logic of its own.

## MCP server (drive Mirrors from an AI client)

The MCP server is now **hosted by Mirrors** — there's nothing to install from this
package. Point any MCP client (Claude Code, Claude Desktop, Codex, Cursor, VS Code,
Zed, …) at the hosted endpoint; on first use the client opens your browser to sign
in and approve access (standard MCP OAuth — no API keys to paste). It exposes the
full Mirrors surface — the same operations as the CLI and the web app, so an AI
client never has to touch the UI: `list_mirrors` / `get_schema` / `get_drift`,
`build_mirror` / `ingest_mirror`, `query_mirror` / `chat_mirror`, `container_start`,
`add_context` / `distill_summary`, `generate_proposal` / `accept_proposal`,
`generate_eval_set` / `run_eval_set`, and more.

> Use the URL **without a trailing slash** (`…/mcp`) — it must match the OAuth
> `resource` the server advertises, and some clients (Cursor) strip a trailing
> slash before comparing. Both forms are served on the wire, but configure the
> slashless one.

```bash
# Claude Code
claude mcp add --transport http mirrors https://api.runmirrors.com/mcp
# Codex
codex mcp add mirrors --url https://api.runmirrors.com/mcp && codex mcp login mirrors
```

```json
{ "mcpServers": { "mirrors": { "url": "https://api.runmirrors.com/mcp" } } }
```

For headless/CI setups you can still skip the browser flow: mint a workspace key
in the web app (Settings → API keys) and send it as an
`Authorization: Bearer mk_live_…` header. Every request is scoped to the
authenticated workspace. (This package ships only the trace **collector** and the
optional `mirrors` CLI.)

## Wire format

Batches are POSTed to `{endpoint}/api/collect` with
`Authorization: Bearer {api_key}`:

```json
{
  "project": "my-agent",
  "traces": [
    {"id": "abc", "model": "gpt-4o", "messages": [{"role": "user", "content": "hi"}]}
  ]
}
```

Failures (non-2xx / network errors) are retried a couple of times then dropped
— the collector never raises into your program.
