Files
tracer-cloud--opensre/docs/python-api.mdx
T

152 lines
4.6 KiB
Plaintext

---
title: "Python API"
slug: "python-api"
description: "Drive the OpenSRE agent in-process from your own Python code"
---
Use this when your Python code runs on the same machine as OpenSRE and you want
agent answers without shelling out to the CLI. To call OpenSRE over the network
instead, use the [HTTP API](/api).
## Prerequisites
The standalone CLI installer does not expose an importable package, so embed
from a source checkout:
```bash
git clone https://github.com/Tracer-Cloud/opensre.git
cd opensre && make install
```
Configure a provider once (`opensre onboard`) — the session API reuses the same
config and credentials as the CLI. Run your script inside the checkout's
environment with `uv run python your_script.py`.
Register adapters before the first turn (tools and investigation):
```python
from bootstrap.process import EMBEDDED_PROFILE, configure_process
configure_process(EMBEDDED_PROFILE)
```
## One API — chat and investigate
Every surface uses the same two verbs:
```python
from core.agent_harness import AgentSession
session = AgentSession.start()
result = session.chat("why is checkout-api slow?")
if result.answered:
print(result.primary_response_text)
report = session.investigate({"alert_name": "HighLatency", "severity": "warning"})
print(report.report)
```
`AgentSession.start()` resolves the environment, opens a session, and attaches
an agent with the standard ports — the same tools and prompts the interactive
shell uses. `investigate` does not require an attached chat agent; it uses the
payload runner installed by `configure_process`.
Always check `result.answered` before trusting chat text: when a turn fails (for
example the LLM provider is unreachable), the error message itself lands in
`result.primary_response_text`.
### Internal seams (not for hosts)
Chat hosts terminate at `dispatch_chat_turn` → `run_turn`. Investigation
terminates at the installed payload runner (`run_investigation_payload`). Do not
invent parallel public entrypoints.
## A conversation
Each `chat` call is one turn in the same session, so follow-ups see earlier
context:
```python
session.chat("list unresolved Sentry issues from the last 24 hours")
result = session.chat("which of those affect checkout?")
```
To resume a previous session instead of starting a new one, pass its ID:
```python
from core.agent_harness import AgentSession, SessionConfig
session = AgentSession.start(SessionConfig(session_id="abc123"))
```
## Your own grounding context
The agent builds its prompts from the session by default. To ground it your own
way — a different system prompt, your own retrieved context — pass a provider:
```python
from core.agent_harness import AgentSession, SessionConfig
session = AgentSession.start(SessionConfig(prompts=my_provider))
```
Omit it and the built-in provider applies
(`core.agent_harness.DefaultPromptContextProvider`). A custom provider must
satisfy `core.agent_harness.ports.PromptContextProvider`. The same `prompts=`
argument is accepted by `build_default_headless_agent` on the custom-ports path
below.
## Custom output and ports
`start()` buffers all output. To capture tool progress yourself — stream to a
websocket, collect for a report — build the agent explicitly and pass your own
sink:
```python
from core.agent_harness import (
AgentSession,
BufferOutputSink,
SessionConfig,
build_default_headless_agent,
)
session = AgentSession(SessionConfig())
startup = session.startup()
sink = BufferOutputSink()
agent = build_default_headless_agent(
session=startup.session,
output=sink,
prompts=my_provider, # optional — same port as SessionConfig.prompts
)
session.attach_agent(agent)
session.chat("summarize open incidents")
print(sink.lines) # rendered output lines
print(sink.streamed) # streamed answer chunks
```
Any object implementing the `OutputSink` protocol
(`core.agent_harness.ports.OutputSink`: `print`, `render_response_header`,
`render_error`, `stream`) works in place of `BufferOutputSink`.
`build_default_headless_agent` also accepts a custom logger, prompt surface,
and tool observers — see its docstring for the full port list.
## Your own tools
Register a package before the first tool lookup:
```python
from tools.registry import register_external_tool_package
import my_agent_tools
register_external_tool_package(my_agent_tools)
```
Two gotchas:
1. Declare tools with `surfaces=("action",)` (or include `"action"`). The
`@tool` default is `("investigation",)` only — the chat/Python-API action
loop will not see investigation-only tools.
2. Tools may live in the package's `__init__.py` or in submodules; both are
scanned after registration.