Repository navigation
Agent Logs OTLP and Langfuse
Langfuse integration is provided by the public official @taichuy/langfuse runtime plugin. Export Agent Flow native chat history and Agent Logs collected history to Langfuse, or import Langfuse traces into a selected Agent Logs application.
The host owns source adapters, conversation/task/event facts, standard OTLP, and authorization. The plugin owns Langfuse APIs, conversion, pagination, and connection settings. Both sources share exchange semantics while retaining their storage responsibilities. Imports create historical log facts, without creating executable Agent Flow runs.
- Obtain the public official Langfuse runtime
.1flowbasepkg, upload it in Extension Center, and activate it. Grant its required contribution permissions and the user's operation permissions. Use a host supporting the pairedApplicationLogsV1andHttpEgressV1callbacks; deploy that host before upgrading the plugin. This acceptance covers uploading the CI package; publishing a registry listing is a separate release step. - Open Settings → Langfuse (
/settings/langfuse) and select Add instance in the shared table. Each saved connection has one row, with pagination, column preferences and a mobile row layout. English and Chinese follow the host’s global language setting. - In the Instance drawer, enter a name, the Langfuse deployment base URL and the destination project's Public key and Secret key. Cloud and self-hosted deployments, including URL path prefixes, are supported. Do not enter a trace page, OTLP endpoint, or a URL containing credentials.
- Click Save, then Reload, verify the row’s name, URL and credential status, then use its Test connection action against the real project API. Each row also offers Edit, Delete, Export and Import. Names and URLs may repeat; a stable
instance_ididentifies the connection and its keys.


The URL is stored in plugin-owned configuration; the host credential service stores both keys. Reading configuration returns the URL and credential presence, without returning keys. The edit drawer opens with blank key fields: leave both blank to retain only this instance’s pair, or provide both to replace it. Renaming retains its identity and keys; deleting removes only this instance and its keys. A legacy connection appears as default. Your 1flowbase server must be able to reach Langfuse. Host Network Center manages egress for the managed-plugin consumer.
- Use the destination Langfuse row’s Export action. In the Export application logs drawer, choose an Agent Flow or Agent Logs source application.
- Enter a record start-time range in RFC3339 with a timezone, for example
2026-10-01T00:00:00+08:00to2026-10-16T00:00:00+08:00. The lower bound is inclusive; the upper bound is exclusive. The range selects complete records, rather than clipping their events. - Click Export complete records. The plugin traverses every selected page and sends each record's complete facts.
- Review
exported_records,exported_spans, andtrace_ids. In the same Langfuse project, locate those trace IDs and inspect inputs, outputs, spans, and metadata.



Records, conversations, traces, and events/spans are different units. A source conversation can contain several tasks. Native exports read full archives, canonical messages, and actual associated calls, rather than substituting UI summaries. Missing timestamps or text do not imply success or task completion.
- Use the source Langfuse row’s Import action. In the Import into AgentLogs drawer, choose the destination Agent Logs application and enable its log reception.
- Enter trace IDs separated by commas, whitespace, or newlines. Alternatively, enable Select traces by date and enter a timezone-aware range.
- Click Import complete traces. Every observation page of a selected trace is read before that trace is converted and imported. Date selection uses the Trace start time with an inclusive lower bound and an exclusive upper bound, then imports the complete selected Trace. Langfuse v4
events_onlydeployments use the supported observations v2 API. - Review
accepted_events,duplicate_events, andrecord_ids. Open the destination logs to inspect conversations and original trajectories. Unchanged repeated source facts are deduplicated; conflicting content under the same identity is rejected.



The host rechecks the actual caller's application access, workspace, operation authorization, and reception state. System-scoped plugin activation does not give a user access to other workspaces. Application API keys authorize ingestion; plugin settings use a signed-in session, CSRF, and independent operation permissions.
Langfuse provides OpenAPI. The plugin reads generated/api/openapi.yml relative to the selected instance URL and uses its saved project credentials. The dedicated exchange APIs above retain the semantic conversion needed for chat analysis; other APIs stay thin so AI can read the live contract and supply parameters.
These are POST endpoints under /api/console/managed-services/langfuse:
| Path | JSON request | Result |
|---|---|---|
/openapi/discover |
{"instance_id":"<id>","search":"observations"}; search and tag optional |
All matching operation IDs, methods, paths, summaries and tags |
/openapi/get |
{"instance_id":"<id>","operationId":"<ID from discover>"} |
Original operation, inherited/overridden parameters and local $ref dependencies; omit operationId for the full specification |
/openapi/execute |
{"instance_id":"<id>","operationId":"<actual ID>","query":{"limit":1}} |
Actual upstream response.status, headers, body_base64, and JSON body when parseable |
Supply path, query, and body as needed, using the upstream field names. Simple scalar paths and form query scalars/arrays are supported. Unsupported encodings and missing path parameters fail explicitly. Only the plugin injects credentials; callers cannot override authentication, arbitrary headers or the URL. Specification servers cannot change the selected destination.
An outer host HTTP 200 indicates a completed call; inspect data.response.status for the upstream outcome. Upstream 403, 404, 429, 500 and other statuses and error bodies are preserved; body_base64 holds authoritative response bytes. The spec is read on each call. There are no availability probes, automatic alternate endpoints, operation substitution or retries. AI reads the actual error and decides what to do next.
The MCP protocol endpoint is /api/mcp/{instance_id}, using the existing managed-service projection at /plugins/langfuse, with four fixed tools: plugin.langfuse.instances.list, plugin.langfuse.openapi.discover, plugin.langfuse.openapi.get, and plugin.langfuse.openapi.execute. Find tools with mcp_list, inspect their contracts with mcp_get, then execute with mcp_call. If a result offers continuation, follow its mcp_result instructions rather than repeating the original operation. The host manages authorization; upstream APIs are discovered as needed instead of each becoming a generated tool.
Before execution, use the return controls advertised by mcp_get.call_parameters. For example, select structured fields in the outer mcp_call request:
{
"tool_id": "plugin.langfuse.openapi.execute",
"arguments": {"instance_id": "<id>", "operationId": "<ID from discover>"},
"response_fields": ["/success", "/response/status", "/response/headers", "/response/body"],
"max_inline_chars": 16000
}max_inline_chars is a caller-selected response budget, not a plugin record-count limit. HTTP retains the complete body_base64; MCP can select status, headers and the complete parsed JSON body, keeping raw base64 out of the default detail view. Selected values use the host’s JSON Pointer entries; follow any returned continuation instructions. outcome: succeeded with detail_unavailable means the operation already ran but its detail is unavailable. Do not repeat the original operation.
Self-export maps the neutral OTLP attribute 1flowbase.agent_log.source_fact to Langfuse metadata 1flowbase_agent_log, as a versioned base64 source-event string, and restores it on import. It preserves source identity, ordering, full content, tools, usage, relationships, and nested raw facts. Missing or conflicting facts are explicit. Malformed or ambiguous self-capsules are rejected. External traces are converted from their actual messages, tools, usage, and relationships; endTime does not imply task success.
Each source batch commits atomically, but a multi-source operation can partially complete. On failure, review the safe error code, confirmed progress, and current-step details. Missing record IDs are not fabricated. Retry unchanged source facts to finish safely; committed events are deduplicated. Remote export rejections or warnings also prevent a claim of complete success. Some deployments process exports asynchronously: an export receipt confirms acceptance; check the stored result in Langfuse.
The plugin adds no business record-count or content-size ceiling. Host deadlines, cancellation, and existing transport safety budgets apply. Exceeding a budget fails explicitly, without silent truncation. Narrow the date range before retrying if needed.
The application Logs page retains Exchange logs → Export/Import OTLP JSON, and native ZIP archives remain separate. Standard OTLP export supports both native and collected sources; imports target Agent Logs.
| Endpoint | Input and result |
|---|---|
POST /api/console/applications/{id}/logs/otlp/export |
Exactly one nonempty record_ids or log_conversation_ids array; returns a standard OTLP JSON object |
POST /api/console/applications/{id}/logs/otlp/import |
{ "otlp": { "resourceSpans": [...] } }; receipt contains accepted/duplicate event counts and record IDs |
Plugin API prefix: /api/console/managed-services/langfuse. Instances provide GET/POST /instances, PUT/DELETE /instances/{instance_id}, and POST /instances/{instance_id}/test. Lists return items, page, page_size, and total, defaulting to page 1 and page size 50 without limiting total instances. GET /applications, POST /records/query, POST /export, and POST /import retain full exchange support; exports/imports supply the selected row’s instance_id. Legacy GET/PUT /config and POST /test address only default; omitting the instance on legacy exchanges also selects only default, never an arbitrary first row. Business results are under data; inspect success. Failures include error.code, optional error.status, and error.details. HTTP 2xx alone does not establish a complete exchange.
The former built-in /logs/langfuse/export and /logs/langfuse/import endpoints have been replaced by the installed settings page and plugin API. API consumers must migrate and use saved credentials. Standard OTLP console endpoints retain their HTTP error semantics, including 409 agent_logs_partial_import; the public SDK receiver uses standard OTLP acknowledgements.
Mobile browser evidence





On 2026-10-15, plugin 0.2.0 passed actual desktop (1440×1000) and mobile (390×844) browser acceptance against Langfuse v4.44.0 OSS, producing 20 real screenshots: plugin CI and package artifacts, host runtime CI. Download the .1flowbasepkg from the plugin CI artifact and upload it in Extension Center. This acceptance package is unsigned; review and acknowledge the known-risk prompt shown during upload.
The plugin source is 1c37a68b. The host binary was built from f8a41c1af; its API source tree matches acceptance candidate a29c39e79 and the then-current dev 23404a0cc. The plugin SDK Git pin is a72190c9b, a different revision from the running host. Relevant log, egress, managed settings, MCP and shared-table contracts were checked for compatibility; these revisions are not claimed to be the same build.
Both viewports passed two-instance create, rename, blank-key preservation, reload, credential isolation, deletion and host English/Chinese switching. Actual exports covered 21 collected events (3 tasks, 2 sessions) and 5 native events, with all 26 unique facts read back from Langfuse. The selected target accepted 26 events on first import; repeat import accepted 0 with 26 duplicates. Date selection imported 2 traces, accepting 0 with 21 duplicates. Complete raw-event equality, stable identities, ordering and historical imports without executable runs all passed.
Live discovery matched all 117 operations in the complete OpenAPI document. Schema references, projects 200, observations 200 and the actual invalid-parameter 400 body and bytes passed. All four fixed MCP tools passed real PAT discovery, description and execution. Execute used the advertised return controls above, with every complete JSON body field matching the actual HTTP result. The exact plugin candidate passed 43 Rust tests in CI. Existing standard OTLP, authorization and frontend evidence was reused only within verified unchanged dependency scopes.
Package SHA-256: 9856b649e09f2f91604eaea39edb34d40415a8cab81bfd7757a260fb5d39936e. Independent cleanup removed temporary instances, credentials, PATs and sessions, restored the original language, and preserved existing connections and candidate node state. Acceptance used isolated candidate ports; the existing 7600 / 7800 services were not restarted. A formal registry listing and hot reinstall into a running host remain outside this verified scope.
The receiver is HTTP Trace only: JSON or protobuf, optionally gzip, at POST /api/logs/otlp/v1/traces. This integration does not provide gRPC, Metrics or Logs receivers. Use an application API key as Authorization: Bearer <APPLICATION_KEY>.
The following configurations match OpenLIT TypeScript 1.15.0 and Python 1.45.0. Initialize instrumentation before the SDK calls you want to observe, using the initialization/import order required by your framework. OpenLIT produces the facts available from the instrumented SDK; it does not automatically capture every human message, agent tool, or task completion.
import OpenLIT from 'openlit';
OpenLIT.init({
otlpEndpoint: 'https://YOUR_HOST/api/logs/otlp',
otlpHeaders: { Authorization: 'Bearer <APPLICATION_KEY>' },
disableMetrics: true,
disableEvents: true,
});This SDK uses the HTTP JSON trace exporter and appends /v1/traces to otlpEndpoint. Do not put that suffix in this base URL twice.
import os
# Set before importing OpenLIT so the HTTP exporter is selected.
os.environ['OTEL_EXPORTER_OTLP_PROTOCOL'] = 'http/protobuf'
os.environ['OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'] = (
'https://YOUR_HOST/api/logs/otlp/v1/traces'
)
import openlit
openlit.init(
otlp_headers={'Authorization': 'Bearer <APPLICATION_KEY>'},
disable_metrics=True,
disable_events=True,
)Python uses the HTTP protobuf exporter by default unless gRPC is configured. The signal-specific trace endpoint above is the full URL. After a real instrumented call, allow the SDK's batch exporter to flush before process exit, then check the application's log records and trajectory.
OpenLIT's CLI can emit Metrics alongside Trace. Configure each additional signal for a backend that supports it; pointing the CLI's general endpoint at this Trace receiver does not establish support for all CLI telemetry.
This standalone Rust plugin declares the direct dependencies below, pinned by its committed Cargo.lock. Its UI reuses host React, Ant Design, @1flowbase/plugin-settings, and the public @1flowbase/data-table; it adds no npm packages.
| Package and locked version | Purpose |
|---|---|
runtime-extension-sdk 0.5.6, pinned to the paired host Git revision |
Shared callbacks, credentials, plugin data, application logs, and egress clients |
tokio 1.53.3 |
Asynchronous managed worker |
serde 1.0.229, serde_json 1.0.154 |
Protocol and log JSON |
base64 0.22.1, sha2 0.10.9 |
Capsules, Basic authentication encoding, stable identifiers |
url 2.5.8, time 0.3.55 |
Service URLs and RFC3339 ranges |
prost 0.14.1 |
Standard OTLP protobuf acknowledgement decoding |
uuid 1.28.0 |
Existing indirect dependency now declared directly with v4 for stable instance IDs |
serde_yaml 0.9.34+deprecated |
Newly declared directly to parse instance OpenAPI YAML into JSON; retains the upstream deprecated marker |
The YAML dependency closure includes ryu 1.0.23 and unsafe-libyaml 0.2.11, reusing existing host/cache versions. Total locked packages increase from 225 to 228. Existing shared external versions, checksums and dependency edges remain unchanged; no dependencies were newly installed locally.