OTEL Worklogs API

Exports AI Employee workflow-execution data as OpenTelemetry (OTLP) traces and logs. The response is standard OTLP TracesData and LogsData serialized to JSON, so it can be ingested by any OTLP-compatible observability backend -- Datadog, Grafana Tempo, Arize, New Relic, Honeycomb, Jaeger, and others.

  • Fetch a single workflow run by ID, or query many runs for one AI Employee over a time range.
  • Returns OTLP traces, plus correlated logs for callers with debug access.
  • Cursor-based pagination for time-range queries.
  • Permission-based filtering: debug-access callers receive full spans and logs; standard viewers receive action and step names, timing, and status only.
  • Exports terminal workflow runs (COMPLETED, FAILED). Within an exported run, individual action spans may carry a paused status when an action awaited human input.
  • Pull-based -- for fetching data after a run reaches a terminal state. It does not stream in real time.

Endpoint

PropertyValue
URL/api/v1/observability/worklogs
HTTP MethodGET
ProtocolHTTP/REST

Headers

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token (JWT or API key). The token determines the caller's permission tier and which tenants and AI Employees are accessible.

Request

The endpoint supports two query modes. If workflow_run_id is present, the request is treated as a single-run lookup. Otherwise it is treated as a time-range query, and persona_id, start_time, and end_time are all required.

ParameterLocationTypeRequiredDescription
workflow_run_idquerystring (UUID)ConditionalSingle-run mode. Fetches one workflow run. Required when persona_id is not provided.
persona_idquerystring (UUID)ConditionalTime-range mode. AI Employee whose runs are exported. Required when workflow_run_id is not provided.
start_timequerystring (RFC 3339)ConditionalStart of the time range. Required in time-range mode.
end_timequerystring (RFC 3339)ConditionalEnd of the time range. Required in time-range mode.
limitqueryintegerNoRuns per page (time-range mode). Default: 100. Min: 1. Max: 500.
page_tokenquerystring (UUID)NoPagination cursor returned as next_page_token in a previous response. Omitted for the first page.

Query Mode: Single Run

curl -H "Authorization: Bearer <access_token>" \
  "https://your-instance.ema.co/api/v1/observability/worklogs?workflow_run_id=<RUN_ID>"

Query Mode: Time Range

curl -H "Authorization: Bearer <access_token>" \
  "https://your-instance.ema.co/api/v1/observability/worklogs?persona_id=<PERSONA_ID>&start_time=2026-03-10T00:00:00Z&end_time=2026-03-11T00:00:00Z&limit=100"

Query Constraints

  • The time-range window must not exceed 7 days per request, and start_time must be before end_time. For longer ranges, issue multiple requests with consecutive windows.
  • limit must be between 1 and 500 (default 100). Use page_token to iterate larger result sets.
  • Only runs in a terminal state (COMPLETED, FAILED) can be exported. A single-run request for a run that is not yet terminal returns 409 Conflict.

Response

A JSON object. traces is always present; logs is present only for callers with debug access and only when log records exist; next_page_token is present only when more pages remain.

FieldTypeDescription
tracesOTLP TracesData (JSON)Workflow execution represented as OTEL traces and spans.
logsOTLP LogsData (JSON)Step-level log records linked to trace and span IDs. Returned only for debug-access callers; omitted otherwise.
next_page_tokenstringPagination cursor for the next page. Omitted when there are no more results.

Note -- the response fields are named traces and logs (each an OTLP protobuf message serialized to JSON), not traces_data / logs_data. For callers without debug access, the logs field is omitted entirely rather than returned empty.

Example Response

{
  "traces": {
    "resourceSpans": [
      {
        "resource": {
          "attributes": [
            { "key": "ema.tenant.id", "value": { "stringValue": "abc12345-0000-0000-0000-000000000000" } },
            { "key": "ema.persona.id", "value": { "stringValue": "2f6c12a8-7d2b-4f1a-9c0e-1234567890ab" } }
          ]
        },
        "scopeSpans": [
          {
            "scope": { "name": "ema.otel.export", "version": "1.0.0" },
            "spans": [
              {
                "name": "Action: Search Knowledge Base",
                "kind": "SPAN_KIND_INTERNAL",
                "status": { "code": "STATUS_CODE_OK" },
                "attributes": [
                  { "key": "ema.action.title", "value": { "stringValue": "Search Knowledge Base" } },
                  { "key": "ema.action.status", "value": { "stringValue": "ACTION_RUN_STATUS_SUCCESS" } },
                  { "key": "ema.action.llm_call_count", "value": { "intValue": "1" } }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

An action that paused for human input during the run is represented by an action span carrying a paused span event, with span status UNSET (see Span Status Mapping). Trace IDs are deterministic for a given run, so re-exporting the same workflow_run_id returns the same trace.

Pagination

For time-range queries returning more results than the page limit, use cursor-based pagination. When more results remain, the response includes a next_page_token and a Link header with rel="next". Pass the token back as page_token and repeat until it is no longer returned.

# First page
curl -H "Authorization: Bearer <access_token>" \
  "https://your-instance.ema.co/api/v1/observability/worklogs?persona_id=<PERSONA_ID>&start_time=2026-03-01T00:00:00Z&end_time=2026-03-08T00:00:00Z&limit=100"

# Response includes: "next_page_token": "<LAST_RUN_ID>"

# Next page
curl -H "Authorization: Bearer <access_token>" \
  "https://your-instance.ema.co/api/v1/observability/worklogs?persona_id=<PERSONA_ID>&start_time=2026-03-01T00:00:00Z&end_time=2026-03-08T00:00:00Z&limit=100&page_token=<LAST_RUN_ID>"

Permission Tiers

The data returned depends on the permission tier of the authenticated caller:

Permission TierTracesLogs
Debug accessFull spans with all exported attributes (LLM metrics, token counts, model names, action statuses)Yes -- step-level log records
Standard viewerAction and step names, timing, and run status onlyNo
  • To receive useful observability data, use an API token with debug access. A standard-viewer token returns only structural information (action and step names, timing, and run status) without LLM metrics or logs.
  • Contact your Ema administrator to configure the appropriate access for your integration account.

Data Exclusions

  • LLM costs (per-call and aggregate) are not included in the export.
  • Prompt content (system prompts, user prompts, model responses) is not included.
  • The export does include metrics such as token counts, latency, and model names -- but not the actual text sent to or received from models.

Trace & Log Attributes

Root Span Attributes

AttributeTypeDescription
ema.tenant.idstringTenant ID.
ema.persona.idstringAI Employee ID.
ema.workflow.run_idstringUnique identifier for the workflow run.
ema.conversation.idstringConversation ID, when the run is tied to one.

Action Span Attributes

AttributeTypeDescription
ema.action.titlestringName of the action.
ema.action.statusstringAction outcome, e.g. ACTION_RUN_STATUS_SUCCESS, ACTION_RUN_STATUS_ERRORED, ACTION_RUN_STATUS_WARNING, ACTION_RUN_STATUS_NOT_RUN, ACTION_RUN_STATUS_PAUSED.
ema.action.llm_latency_msfloatTotal LLM latency within the action, in milliseconds.
ema.action.llm_call_countintegerNumber of LLM calls in the action.

LLM Call Span Attributes

LLM call spans follow the OpenTelemetry GenAI semantic conventions where applicable:

AttributeTypeDescription
gen_ai.provider.namestringLLM provider (e.g. openai, anthropic, google).
gen_ai.request.modelstringModel requested.
gen_ai.response.modelstringModel that responded (may differ if routed).
gen_ai.usage.input_tokensintegerInput token count.
gen_ai.usage.output_tokensintegerOutput token count.
ema.llm.latency_sfloatLLM call duration, in seconds.
ema.llm.successbooleanWhether the call succeeded.
ema.llm.error_messagestringError message, if the call failed.
ema.llm.fusion_usedbooleanWhether EmaFusion™ model routing was used.
ema.llm.optimization_criteriastringOptimization strategy used for model selection.

Log Record Attributes

Included in logs for debug-access callers only. Each record also carries standard OTLP traceId, spanId, severity, and body fields linking it to its parent span.

AttributeTypeDescription
ema.action.titlestringParent action name.
ema.step.namestringParent step name, for step-level messages.
ema.workflow.run_idstringWorkflow run ID.
ema.persona.idstringAI Employee ID.

Span Status Mapping

Action Run StatusOTEL Span StatusNotes
SUCCESSOK
ERROREDERRORStatus message action errored.
WARNINGUNSETA WARNING span event is attached.
NOT_RUNUNSET
PAUSEDUNSETA paused span event is attached.

Error Responses

HTTP StatusDescription
400Invalid or missing parameters: a malformed UUID (workflow_run_id, persona_id, or page_token); a missing persona_id, start_time, or end_time in time-range mode; non-RFC 3339 timestamps; start_time not before end_time; a time range over 7 days; or limit outside 1-500.
401Missing or invalid authorization (no tenant context).
403Caller lacks permission for the requested AI Employee or tenant.
404Workflow run not found, or it belongs to a tenant the caller cannot see (single-run mode).
409The workflow run is not yet in a terminal state (still executing).
500Server error while retrieving data or building the OTLP export.

Last updated: Jul 17, 2026