Skip to main content

agent-status-sdk (Python)

Live tools/call traffic from your MCP server into AgentStatus User Traffic and Analytics.

This package does not register HTTP agents, run residential probes, open a tunnel, or expose Agent Status as an MCP server. Those were the old SDK. Gone in 2.0.0.

Your public MCP URL does not change. Hosts keep calling origin. observe() wraps the process you already run.

Install

pip install agent-status-sdk

No extra extras. Stdlib only.

What you need from the dashboard

On the MCP agent, User Traffic tab, copy the agent id. That is a UUID, not an API key.

Set it in code or in the environment:

export AGENTSTATUS_AGENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Optional:

export AGENTSTATUS_INGEST="https://api.rora.carmel.so/api/rora"

Default ingest is already that URL. You do not pass a Fabric/Rora API key. The observe route is public per agent id, same threat model as the live-mcp URL.

FastMCP

Register tools first, then wrap, then run.

from mcp.server.fastmcp import FastMCP
from agent_status import observe

mcp = FastMCP("docs")

@mcp.tool()
def search_docs(q: str) -> str:
    return "..."

observe(mcp, agent_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
mcp.run()

If AGENTSTATUS_AGENT_ID is set, observe(mcp) is enough.

Low-level MCP Server

from mcp.server import Server
from agent_status import observe

server = Server("docs")
observe(server, agent_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")

Call observe() after the server object exists. If your framework registers CallTool lazily, call it after tools are registered and before run().

If the wrap cannot find tools/call, stderr prints a warning and the server still runs. Pass observe(..., required=True) if you want boot to fail instead. Do not use track() with an MCP id.

What gets recorded

On each tools/call:

  • tool name (job)
  • duration (time inside the handler)
  • RPC / exception error text, truncated
  • host name and version from initialize.clientInfo when the wrap saw initialize
  • session id if you pass it on report_tool_call
  • a short result excerpt

User Traffic is the event list. Analytics rolls those events (mix, week vs week, errors, latency). Cost and tokens only if you send them. We do not invent them.

observe() does not store names, email, chat, or the host thread. Arguments are forwarded as a dict; do not put secrets in tool args if you cannot afford them leaving the process. The ingest strips a small blocked-key set (email, chat, prompt, …) but that is not a privacy guarantee.

Fail-open

The tool handler always runs first. Recording is a background POST with a 2 second timeout. If AgentStatus is down, DNS fails, or the wrap cannot find a handler, the tool still returns. We miss a row. The customer does not miss a response.

observe() itself never raises into your server. A bad server object is returned unchanged.

If Analytics is empty

  1. observe() is not on the process hosts actually hit.
  2. You wrapped after run(), or before setRequestHandler / tool registration in a way the wrap missed. Check stderr for the wrap warning.
  3. Origin is still serving a second copy of the server without the wrap.
  4. Hosts are calling a different deployment than the one with AGENTSTATUS_AGENT_ID.
  5. You called track() with an MCP id, or observe() with a personal-agent id. Ingest rejects that.

Connection tests from AgentStatus are our probes. They are not live user traffic.

Personal agents (Agent)

Use Agent, not observe(). Bind once per thread. Wrap the dispatcher once. get_calendar maps to calendar.

from agent_status import Agent

ember = Agent(agent_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")

def handle_thread(thread):
    bound = ember.bind(user=thread.anon_id, session=thread.id)

    def check_landed(name, result):
        # True or False after you look. None skips landing.
        return None

    call_tool = bound.wrap_tools(call_tool, landed=check_landed)
    return call_tool("get_calendar", {"when": "tomorrow"})

That one wrap is User Traffic and Analytics. Landing is opt-in: return {..., "landed": False} from the tool, or pass landed=. If you skip it, the dashboard shows Not reported. run.miss() still works inside job().

track("calendar", ...) still works for a single job.

Manual report

If you are not using the official MCP Server classes:

from agent_status import report_tool_call

report_tool_call(
    name="search_docs",
    agent_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    duration_ms=21,
    provider="cursor",
)

Never raises.

What this is not

  • Not a sidecar. Not a public URL swap.
  • Not session replay of Cursor / Claude Code.
  • Not hallucination grouping.
  • Not wrapping the host. We wrap your server.

Ingest

POST https://api.rora.carmel.so/api/rora/public/live-mcp/{agent_id}/observe

JSON body, name required. This path only records. It does not proxy to origin and does not run the tool.

Metadata

Release files for agent-status-sdk 2.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-status-sdk 2.3.0
File Size Uploaded Provenance
agent_status_sdk-2.3.0.tar.gz 11.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-status-sdk 2.3.0
File Interpreter ABI Platform
agent_status_sdk-2.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.0 kB

Release files / agent_status_sdk-2.3.0.tar.gz

Download URL agent_status_sdk-2.3.0.tar.gz
Size 11.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a597894e157146509c9261a000f5483c4884264257ce4a0e96bae0b8212a47e6
BLAKE2b-256 checksum
How to use checksums
53f1c36365c6a6d562686812043a22d6d914b2858029bb5eb743e95901414aa7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / agent_status_sdk-2.3.0-py3-none-any.whl

Download URL agent_status_sdk-2.3.0-py3-none-any.whl
Size 9.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6cfbaad4ae52d3e17e05868f63e7d75c8258d75c2f2a782b5000d7bccc0057b
BLAKE2b-256 checksum
How to use checksums
f5aa8f240c4c4df5238b9cc6ea5504b9a390318f76c322dc798c155193c33079
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for agent-status-sdk 2.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page