Monitoring
Send every span your agent produces to Harbor, where each trace is scored.
Monitoring is how production behaviour reaches Harbor. You add the SDK for your language, and every LLM call, tool call, retrieval and agent step your agent makes becomes an OpenTelemetry span. Spans are batched in the background and shipped to Arc, which reconstructs the trajectory, groups turns into sessions, and runs its risk assessment on each one.
Harbor reads the OpenTelemetry GenAI semantic conventions and never rewrites your attributes on the way out. Any framework already emitting those conventions is understood as-is, which is why the integrations below are a few lines rather than an adapter each.
How traces reach Harbor
Export is asynchronous and fails open. A missing key, an unreachable endpoint or a rejected batch is logged once and dropped; your agent's request path is never blocked by monitoring, and no Harbor call can throw into it.
Pick an integration
TypeScript SDK
harbor-ai-sdk for Node.js: the client, capture, and your own spans.
Vercel AI SDK
AI SDK v7 emits GenAI spans natively. Register Harbor and they arrive.
Mastra
Add HarborExporter to Mastra's observability config.
Flue
Register @flue/opentelemetry alongside Harbor's tracer provider.
Eve
Add HarborSpanProcessor to Eve's registerOTel instrumentation.
OpenTelemetry
Any language, any exporter. Point OTLP at the ingestion endpoint.
No SDK for your language, or a collector already aggregating your traces? Harbor's endpoint is plain OTLP/HTTP — see OpenTelemetry.
Before you start
You need a Harbor API key
Create one in the Harbor platform under system settings. It is sent as a bearer token on every export and identifies both the organization and the system the spans belong to — there is no system id to configure in code.
export HARBOR_API_KEY=...
export HARBOR_BASE_URL=https://api.harbor.aiBoth are read from the environment, so a working setup is normally one constructor call.
Spans are posted to <HARBOR_BASE_URL>/v1/traces; a base URL that already ends in
/v1/traces is used as given. With either variable missing the SDK warns once and every
integration becomes a no-op, so an unconfigured environment is quiet rather than broken.
What Harbor builds from your spans
| Concept | Where it comes from |
|---|---|
| Span | One operation: a model call, a tool execution, an agent step |
| Trace | One execution — an agent run or a conversation turn, with its nested spans |
| Session | Several traces sharing a session id: a multi-turn conversation |
| Agent | gen_ai.agent.name |
| User | user.id |
| Risk score | Computed by Harbor on each ingested trace and trajectory |
Span kinds are read from gen_ai.operation.name:
| Value | Meaning |
|---|---|
chat | A model call |
execute_tool | A tool the agent invoked |
invoke_agent | An agent or sub-agent run |
embeddings / retrieval | Embedding and retrieval steps |
guardrail | A guardrail verdict |
Your framework sets these. You only set them on spans you create yourself.
Monitoring covers traces. OTLP metrics and logs are not ingested — send those to your existing observability backend, which can run alongside Harbor on the same tracer provider.