Metadata-Version: 2.4
Name: mirrorkit
Version: 0.2.5
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://www.runmirrors.com/
Project-URL: Documentation, https://www.runmirrors.com/docs
Project-URL: Pricing, https://www.runmirrors.com/pricing
Keywords: llm,ai-agents,agent-testing,agent-replay,agent-evaluation,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_...", environment="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_...",
    environment="my-agent",
    endpoint="https://api.runmirrors.com",  # 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_...", environment="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_...", environment="my-agent")
chain.invoke(inputs, config=RunnableConfig(callbacks=[mirrorkit.handler()]))
```

## API

- `mirrorkit.init(api_key, environment="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 setup                                  # make a mirror (start here)
mirrors env ls                                 # list environments
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                                  # replay-minutes vs. included allowance
```

### Making a mirror: `mirrors setup`

`mirrors setup` is the front door. It runs the same onboarding conversation as the
web app and the MCP tools: it asks what to call the environment, prints a link to
install the GitHub App (and opens your browser if there is one), reads the repo,
asks which agent to mirror, asks whether you already have traces, takes any docs or
an OpenAPI spec, builds, and shows you the twin.

```bash
mirrors setup                    # start, or pick the last conversation back up
mirrors setup argonaut           # name a new one up front
mirrors setup --session <id>     # resume a specific one
mirrors setup --reset            # start the conversation over
```

Answer however suits: a numbered list takes its number, a drop box takes file paths
(globs are fine), and typing a sentence works at any prompt. That includes a question
back ("what kinds of docs?"), which gets answered without losing the prompt you were
on. Ctrl-C only stops watching, the work carries on server-side.

For scripting, `--json` (or `--say` / `--choice` / `--attach`) does one thing and
prints the session, with no prompts and no polling.

**No GitHub?** `mirrors build` uploads files instead, and it is not going anywhere:
it is the path for GitLab, self-hosted and Bitbucket repos, for trying Mirrors out
before connecting anything, and for rebuilding an environment from its collected
stream.

```bash
mirrors build traces.jsonl --name airline      # ingest + build a twin (streams the log)
mirrors build --environment airline            # rebuild from its collected stream
```

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
{
  "environment": "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.
