Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion openhands/usage/agent-canvas/backend-setup/docker.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
title: Docker Backend
description: Run Agent Canvas in a Docker container as a sandboxed backend.

Check warning on line 3 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L3

Did you really mean 'sandboxed'?
---

The official Docker image packages the full Agent Canvas stack — backend and frontend — in a single container. The agent runs inside the container rather than directly on your host, giving you a sandboxed environment out of the box.

Check warning on line 6 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L6

Did you really mean 'sandboxed'?

## Prerequisites

Expand All @@ -17,7 +17,7 @@
<Tabs>
<Tab title="macOS / Linux">
```bash
mkdir -p ~/projects ~/.openhands

Check warning on line 20 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L20

Did you really mean 'mkdir'?

docker run -it --rm \
-p 8000:8000 \
Expand Down Expand Up @@ -52,13 +52,103 @@
| Variable | Purpose |
|----------|---------|
| `PORT` | Ingress port inside the container (default `8000`). Map it with `-p <host>:<PORT>`. |
| `LOCAL_BACKEND_API_KEY` | API key for the server. Auto-generated and persisted if not set. |
| `LOCAL_BACKEND_API_KEY` | API key for the Agent Canvas backend API. Auto-generated and persisted if not set. |
| `OH_SECRET_KEY` | Secret used to protect stored settings and secrets. |
| `LMNR_PROJECT_API_KEY` | Enables built-in SDK tracing to Laminar. |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Enables built-in SDK trace export to an OTLP-compatible backend such as Jaeger, Honeycomb, Datadog, New Relic, or Grafana Tempo. |

Check warning on line 58 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L58

Did you really mean 'Datadog'?

Check warning on line 58 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L58

Did you really mean 'Grafana'?
| `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | OTLP transport protocol, usually `http/protobuf` or `grpc`. |
| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | Optional authentication headers for your OTLP backend. |

For the full tracing reference, see [Observability & Tracing](/sdk/guides/observability).

<Warning>
The agent server can execute arbitrary shell commands inside the container. If exposing it beyond localhost, set `LOCAL_BACKEND_API_KEY` to a strong secret.
</Warning>

## View Backend Conversations and Events

Agent Canvas includes a backend API for conversations and events. This is built in and uses the same `LOCAL_BACKEND_API_KEY` that the UI uses. It is separate from observability tracing.

Use this API if you need to inspect conversations stored in the Docker backend, including a conversation that is not visible in the left panel.

```bash icon="terminal" wrap
# Use the value you passed as LOCAL_BACKEND_API_KEY.
# If you did not set one, check the container logs for the generated key.
export LOCAL_BACKEND_API_KEY="your-backend-api-key"

curl -sS \
-H "X-Session-API-Key: $LOCAL_BACKEND_API_KEY" \
http://localhost:8000/api/conversations/search
```

After you find a conversation ID, inspect recent events:

```bash icon="terminal" wrap
export CONVERSATION_ID="conversation-id"

curl -sS \
-H "X-Session-API-Key: $LOCAL_BACKEND_API_KEY" \
"http://localhost:8000/api/conversations/$CONVERSATION_ID/events/search?limit=20"
```

<Note>
Observability exporters do not backfill old conversations. Set up tracing before starting the conversations you want to observe.
</Note>

## Built-in Tracing vs. External Backends

Built into Agent Canvas Docker:

- The OpenHands Agent Server runs inside the container and uses the OpenHands SDK.
- The SDK automatically emits traces when Laminar or OTEL environment variables are present.
- The backend conversation and event APIs are available behind `LOCAL_BACKEND_API_KEY`.

Not built into Agent Canvas Docker:

- A Prometheus `/metrics` endpoint for scraping agent execution metrics.
- A Grafana connector that authenticates into Agent Canvas or makes conversations appear in the left panel.

Check warning on line 109 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L109

Did you really mean 'Grafana'?
- Hosted Laminar, Jaeger, Tempo, Prometheus, Grafana, Datadog, Honeycomb, or New Relic services. Those are external observability systems you run or subscribe to separately.

Check warning on line 110 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L110

Did you really mean 'Grafana'?

Check warning on line 110 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L110

Did you really mean 'Datadog'?

The SDK also has built-in token, cost, and latency tracking for SDK-based integrations; see [Metrics Tracking](/sdk/guides/metrics). That is different from service metrics scraped by Prometheus.

For Grafana, the typical tracing setup is to export OTLP traces from Agent Canvas to Grafana Tempo or another trace backend, then add that backend as a Grafana data source. Prometheus is useful for metrics, but the SDK tracing exporter sends traces, not Prometheus scrape metrics.

Check warning on line 114 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L114

Did you really mean 'Grafana'?

## Enable SDK Tracing

The Docker image starts the OpenHands Agent Server inside the container, and the Agent Server uses the OpenHands SDK. To enable tracing for Agent Canvas conversations, pass Laminar or OpenTelemetry environment variables to `docker run`.

### Laminar example

```bash icon="terminal" wrap
mkdir -p ~/projects ~/.openhands

docker run -it --rm \
-p 8000:8000 \
-e LMNR_PROJECT_API_KEY="your-laminar-api-key" \
-v ~/.openhands:/home/openhands/.openhands \
-v ~/projects:/projects \
ghcr.io/openhands/agent-canvas:latest
```

### OTLP collector example

If your collector runs on your host machine, remember that `localhost` inside the container means the Agent Canvas container itself. Use `host.docker.internal` on Docker Desktop, or add the host gateway alias on Linux.

```bash icon="terminal" wrap
mkdir -p ~/projects ~/.openhands

docker run -it --rm \
--add-host=host.docker.internal:host-gateway \
-p 8000:8000 \
-e OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://host.docker.internal:4317" \
-e OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="grpc" \
-v ~/.openhands:/home/openhands/.openhands \
-v ~/projects:/projects \
ghcr.io/openhands/agent-canvas:latest
```

If the collector runs in another container, put both containers on the same Docker network and use the collector's container or Compose service name in the endpoint, for example `http://jaeger:4317`.

## Connect from the Frontend

Start the frontend separately and point it at the container:
Expand Down
2 changes: 2 additions & 0 deletions openhands/usage/agent-canvas/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ description: Install and run Agent Canvas via npm or Docker.
| `PORT` | Ingress port inside the container (default `8000`). Map it with `-p <host>:<PORT>`. |
| `LOCAL_BACKEND_API_KEY` | API key for the server. Auto-generated and persisted if not set. |
| `OH_SECRET_KEY` | Secret used to protect stored settings and secrets |

To enable SDK tracing from the Docker image, pass `LMNR_*` or `OTEL_*` variables with `-e`. See [Docker Backend](/openhands/usage/agent-canvas/backend-setup/docker#enable-sdk-tracing) and [Observability & Tracing](/sdk/guides/observability).
</Tab>
</Tabs>

Expand Down
8 changes: 8 additions & 0 deletions sdk/guides/observability.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Observability & Tracing
description: Enable OpenTelemetry tracing to monitor and debug your agent's execution with tools like Laminar, MLflow, Honeycomb, or any OTLP-compatible backend.

Check warning on line 3 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L3

Did you really mean 'MLflow'?
---

> A full setup example is available [below](#example-full-setup).
Expand All @@ -12,7 +12,7 @@
- **[Laminar](https://laminar.sh/)** - AI-focused observability with trace inspection, signals, and browser session replay
- **[MLflow](https://mlflow.org/)** - Open-source AI platform with tracing, evaluation, and LLM governance
- **[Honeycomb](https://www.honeycomb.io/)** - High-performance distributed tracing
- **Any OTLP-compatible backend** - Including Jaeger, Datadog, New Relic, and more

Check warning on line 15 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L15

Did you really mean 'Datadog'?

The SDK automatically traces:
- Agent execution steps
Expand All @@ -36,8 +36,12 @@

That's it. Run your agent code normally and traces will be sent to Laminar automatically.

<Note>
If you run Agent Canvas with Docker, set the Laminar or OTEL variables on the Agent Canvas container. The built-in part is SDK trace instrumentation and OTLP export; Laminar, Jaeger, Grafana Tempo, and other collectors are external systems you configure separately. See [Docker Backend](/openhands/usage/agent-canvas/backend-setup/docker#built-in-tracing-vs-external-backends) for `docker run` examples, backend API inspection, and Docker networking notes.

Check warning on line 40 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L40

Did you really mean 'Grafana'?
</Note>

<Note>
For Laminar-specific walkthroughs, see the official docs for [OpenHands SDK tracing](https://laminar.sh/docs/tracing/integrations/openhands-sdk), [session replay for browser agents](https://laminar.sh/docs/tracing/browser-agent-observability), [viewing traces](https://laminar.sh/docs/platform/viewing-traces), and [signals](https://laminar.sh/docs/signals/introduction).

Check warning on line 44 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L44

Did you really mean 'walkthroughs'?
</Note>

For **self-hosted Laminar** deployments, you can also configure custom ports:
Expand All @@ -48,13 +52,13 @@
export LMNR_GRPC_PORT=8001
```

If you need help deciding between Laminar Cloud and self-hosted Laminar, see Laminar's official [hosting options](https://laminar.sh/docs/hosting-options).

Check warning on line 55 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L55

Did you really mean 'Laminar's'?

### Why use Laminar with OpenHands?

Laminar is especially useful when you want to understand how an agent behaved across one run or across many runs:

- Inspect a single run in transcript, tree, or timeline views to see prompts, tool calls, outputs, and nested agent activity. See Laminar's guide to [viewing traces](https://laminar.sh/docs/platform/viewing-traces).

Check warning on line 61 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L61

Did you really mean 'Laminar's'?
- Watch browser automation alongside trace spans with [session replay for browser agents](https://laminar.sh/docs/tracing/browser-agent-observability).
- Define [signals](https://laminar.sh/docs/signals/introduction) to classify failures, user friction, or success patterns across many traces.
- Keep each OpenHands conversation grouped under a single session ID so multi-turn debugging is easier.
Expand Down Expand Up @@ -175,8 +179,8 @@

The SDK supports both HTTP and gRPC protocols:

- **`http/protobuf`** or **`otlp_http`** - HTTP with protobuf encoding (recommended for most backends)

Check warning on line 182 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L182

Did you really mean 'protobuf'?
- **`grpc`** or **`otlp_grpc`** - gRPC with protobuf encoding (use only if your backend supports gRPC)

Check warning on line 183 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L183

Did you really mean 'protobuf'?

## Platform-Specific Configuration

Expand Down Expand Up @@ -212,24 +216,24 @@
6. Save that key as the **Laminar Project API Key** in the Admin Console.
7. Redeploy, then start a conversation in OpenHands.

In OHE, environment variables with `LMNR_` and `LLM_` prefixes are automatically forwarded to the SDK runtime. That makes it possible to configure Laminar endpoint settings such as `LMNR_BASE_URL`, `LMNR_PROJECT_API_KEY`, and `LMNR_FORCE_HTTP`, as well as the LLM that powers Laminar's own AI features (chat-with-trace, SQL-with-AI, and [signals](https://laminar.sh/docs/signals/introduction)) via `LLM_PROVIDER`, `LLM_BASE_URL`, and `LLM_MODEL_SMALL|MEDIUM|LARGE`.

Check warning on line 219 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L219

Did you really mean 'Laminar's'?

`LLM_PROVIDER` accepts `gemini` (Laminar's default), `openai`, or `bedrock`. Set it to `openai` whenever you point `LLM_BASE_URL` at an OpenAI-compatible gateway (for example LiteLLM, OpenRouter, or vLLM), not just the public OpenAI API. For the full list of supported values, see Laminar's official [self-hosting configuration reference](https://laminar.sh/docs/self-hosting/configuration).

Check warning on line 221 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L221

Did you really mean 'Laminar's'?

Check warning on line 221 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L221

Did you really mean 'Laminar's'?

For the full OHE flow with screenshots and configuration examples, see [Analytics in OpenHands Enterprise](/enterprise/analytics).

### MLflow Setup

Check warning on line 225 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L225

Did you really mean 'MLflow'?

[MLflow](https://mlflow.org/) is an open-source AI platform that accepts OpenTelemetry traces out of the box, alongside evaluation and LLM governance capabilities.

1. Start your MLflow tracking server:

Check warning on line 229 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L229

Did you really mean 'MLflow'?

```bash icon="terminal" wrap
uvx mlflow server
```

<Note>
For other deployment options (pip, Docker Compose, etc.), see [Set Up MLflow Server](https://mlflow.org/docs/latest/genai/getting-started/connect-environment/).

Check warning on line 236 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L236

Did you really mean 'MLflow'?
</Note>

2. Configure the environment variables:
Expand All @@ -240,7 +244,7 @@
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
```

Navigate to the MLflow UI (for example, `http://localhost:5000`), select the experiment, and open the **Traces** tab to view the recorded traces.

Check warning on line 247 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L247

Did you really mean 'MLflow'?

### Honeycomb Setup

Expand Down Expand Up @@ -272,6 +276,10 @@

Access the Jaeger UI at `http://localhost:16686`.

<Note>
If OpenHands is running inside an Agent Canvas Docker container, do not use `http://localhost:4317` for a collector running on your host. Use `http://host.docker.internal:4317` on Docker Desktop, add a host gateway alias on Linux, or put both containers on the same Docker network and use the collector's service name.
</Note>

### Generic OTLP Collector

For other backends, use their OTLP endpoint:
Expand Down Expand Up @@ -335,7 +343,7 @@

4. **Validate headers**: Check that authentication headers are properly URL-encoded.

For Laminar-specific troubleshooting, see Laminar's official [tracing troubleshooting guide](https://laminar.sh/docs/tracing/troubleshooting).

Check warning on line 346 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L346

Did you really mean 'Laminar's'?

## Troubleshooting

Expand Down Expand Up @@ -364,7 +372,7 @@

**Solutions**:
- Tracing has minimal overhead when properly configured
- Disable tracing in development by unsetting environment variables

Check warning on line 375 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L375

Did you really mean 'unsetting'?
- Use asynchronous exporters (default in most OTLP configurations)

## Example: Full Setup
Expand Down Expand Up @@ -429,5 +437,5 @@

- **[Analytics in OpenHands Enterprise](/enterprise/analytics)** - Deploy Laminar inside OHE and send conversation traces automatically
- **[Metrics Tracking](/sdk/guides/metrics)** - Monitor token usage and costs alongside traces
- **[LLM Registry](/sdk/guides/llm-registry)** - Track multiple LLMs used in your application

Check warning on line 440 in sdk/guides/observability.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/observability.mdx#L440

Did you really mean 'LLMs'?
- **[Security](/sdk/guides/security)** - Add security validation to your traced agent executions
Loading