npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shichen335/openclaw-logfire

v1.0.0

Published

Pydantic Logfire observability plugin for OpenClaw — OTEL GenAI semantic conventions, distributed tracing, token metrics, trace links

Downloads

174

Readme

@shichen335/openclaw-logfire

npm version License: MIT

openclaw-logfire sends OpenClaw agent activity to Pydantic Logfire as OTLP traces and metrics.

It captures the real execution shape of an OpenClaw run:

  • one root invoke_agent span per agent invocation
  • staged chat <model> spans reconstructed from llm_input and llm_output
  • one execute_tool <tool> span per tool call
  • token usage metrics and cumulative session usage
  • optional traceparent injection for HTTP commands such as curl, wget, http, and httpie

The plugin is designed around the latest OpenClaw hook flow and OTEL GenAI semantic conventions, while staying practical about privacy controls and debugging.

Requirements

  • OpenClaw >= 2026.2.1
  • Node.js >= 20
  • A Logfire write token
  • Network access to Logfire OTLP endpoints:
    • https://logfire-us.pydantic.dev
    • https://logfire-eu.pydantic.dev

Install

For most users, install it as an OpenClaw plugin:

openclaw plugins install @shichen335/openclaw-logfire

Then enable it in openclaw.json:

{
  "plugins": {
    "entries": {
      "openclaw-logfire": {
        "enabled": true,
        "config": {}
      }
    }
  }
}

The plugin id must be openclaw-logfire.

Get A Logfire Write Token

This plugin uses a Logfire write token. The environment variable name is LOGFIRE_TOKEN.

  1. Open Logfire Login and sign up or sign in.
  2. If this is your first time in Logfire, finish the onboarding flow.
  3. If you want a dedicated project for OpenClaw, open Organization > Projects and create one.
  4. Open the target project.
  5. Go to Settings > Write tokens.
  6. Click New write token.
  7. Copy the token immediately. Logfire does not show the full token again later.
  8. Export it in your shell:
export LOGFIRE_TOKEN="<your-write-token>"

Useful official links:

Quick Start

Minimal configuration:

{
  "plugins": {
    "entries": {
      "openclaw-logfire": {
        "enabled": true,
        "config": {}
      }
    }
  }
}

Then restart OpenClaw. The plugin reads LOGFIRE_TOKEN at runtime and starts exporting spans.

If LOGFIRE_TOKEN is missing, the plugin disables itself and logs an error instead of starting half-configured.

Recommended Configuration

This example is based on a real OpenClaw setup and works well when you want rich debugging and full message capture. Replace placeholders before use.

{
  "plugins": {
    "entries": {
      "openclaw-logfire": {
        "enabled": true,
        "config": {
          // Prefer LOGFIRE_TOKEN via environment variable.
          // You can set "token" here, but env var is safer.
          "projectUrl": "https://logfire.pydantic.dev/<org>/<project>",

          // Map non-standard provider ids to OTel-friendly names.
          "providerNameMap": {
            "customprovider": "openai"
          },

          // Full payload capture for debugging.
          "captureMessageContent": true,
          "captureHistoryMessages": true,
          "historyMessagesMaxLength": 100000,
          "toolInputMaxLength": 100000,
          "toolOutputMaxLength": 16384,

          // Privacy and persistence switches.
          "redactSecrets": false,
          "saveHookLogs": false
        }
      }
    }
  }
}

Notes:

  • projectUrl enables clickable trace links when enableTraceLinks is on.
  • providerNameMap is useful when your OpenClaw provider id is not a standard OTel GenAI provider name.
  • captureMessageContent: true also increases what can be captured from tool inputs and outputs. Review privacy expectations before enabling it.
  • captureToolDefinitions is accepted by the schema, but it is currently reserved and does not change runtime behavior in 1.0.0.

What The Plugin Captures

Span tree

A typical trace looks like this:

invoke_agent main
  |- chat gpt-5.4
  |- running 2 tools
  |   |- execute_tool Read
  |   `- execute_tool Shell
  `- chat gpt-5.4

Root span

The root invoke_agent <agent> span stores:

  • conversation id and channel metadata when available
  • cumulative input, output, cache read, and cache write token counts
  • tool count and overall duration
  • reconstructed pydantic_ai.all_messages
  • final_result when a final assistant result can be extracted

Chat spans

The plugin does not keep a single long-lived chat span open through the whole turn. Instead, it reconstructs one or more chat <model> spans from the final conversation shape emitted by llm_output.

That means:

  • tool-call boundaries appear as separate chat phases
  • final assistant content is more accurate when OpenClaw emits llm_output after lastAssistant is fully assembled
  • if lastAssistant is incomplete, the plugin falls back to assistantTexts

Tool spans

Each tool call becomes execute_tool <tool>.

Depending on configuration, the span may include:

  • gen_ai.tool.call.arguments
  • gen_ai.tool.call.result
  • output size and timing metadata

Tool calls from the same runId also produce a synthetic group span such as running 1 tool or running 3 tools.

Metrics

When enableMetrics is true, the plugin exports:

  • gen_ai.client.token.usage
  • gen_ai.client.operation.duration

Configuration Reference

All config lives under plugins.entries.openclaw-logfire.config.

Environment variable fallbacks

| Variable | Used for | Notes | |---|---|---| | LOGFIRE_TOKEN | token | Required at runtime unless token is set directly | | LOGFIRE_PROJECT_URL | projectUrl | Optional | | LOGFIRE_ENVIRONMENT | environment | Defaults to development | | LOGFIRE_PROVIDER_NAME | providerName | Optional |

Active runtime options

These options are parsed by the config resolver and currently affect runtime behavior.

| Key | Type | Default | Description | |---|---|---:|---| | token | string | "" | Logfire write token. Prefer LOGFIRE_TOKEN instead of committing it into config. | | projectUrl | string | "" | Project URL used to build clickable trace links. | | region | "us" \| "eu" | "us" | Selects the OTLP base endpoint. | | environment | string | "development" | Deployment environment resource attribute. | | serviceName | string | "openclaw-agent" | OTEL service.name. | | providerName | string | "" | Default provider name when OpenClaw metadata does not provide one. | | providerNameMap | Record<string, string> | {} | Maps OpenClaw provider ids to OTEL provider names. | | captureToolInput | boolean | true | Captures tool arguments. | | captureToolOutput | boolean | false | Captures tool results. | | toolInputMaxLength | integer | 2048 | Truncation limit for tool input capture. | | toolOutputMaxLength | integer | 512 | Truncation limit for tool output capture and chat output capture. | | captureMessageContent | boolean | false | Captures chat input, chat output, and system instructions. Privacy-sensitive. | | captureHistoryMessages | boolean | false | Helps reconstruct multi-turn conversation history on the root span. | | historyMessagesMaxLength | integer | 16384 | Truncation limit for serialized history messages. | | redactSecrets | boolean | true | Redacts common API keys, bearer tokens, JWTs, passwords, and similar secrets before capture. | | distributedTracing.enabled | boolean | false | Enables command-level trace propagation. | | distributedTracing.injectIntoCommands | boolean | true | Injects traceparent into matching HTTP commands. | | distributedTracing.urlPatterns | string[] | ["*"] | URL glob patterns that are allowed for injection. | | enableMetrics | boolean | true | Enables OTLP metric export. | | metricsIntervalMs | integer | 60000 | Metric export interval in milliseconds. | | enableTraceLinks | boolean | true | Logs clickable project trace links when projectUrl is configured. | | saveHookLogs | boolean | false | Persists raw hook payloads to ~/.openclaw/logs/ for debugging. | | resourceAttributes | Record<string, string> | {} | Additional OTEL resource attributes. | | spanProcessorType | "batch" \| "simple" | "batch" | Use simple when debugging exporter behavior. | | batchConfig.maxQueueSize | integer | 2048 | Batch span processor queue size. | | batchConfig.maxExportBatchSize | integer | 512 | Maximum spans per export batch. | | batchConfig.scheduledDelayMs | integer | 5000 | Delay between batch exports. |

Accepted but currently reserved options

These keys are accepted by the schema and config resolver, but they are not fully wired into runtime behavior in 1.0.0.

| Key | Current status | |---|---| | captureStackTraces | Reserved. Current runtime does not branch on this flag. | | captureToolDefinitions | Reserved. Accepted by schema, but not currently attached to spans. | | distributedTracing.extractFromWebhooks | Reserved. Current implementation focuses on outbound command injection. | | logLevel | Reserved. Accepted by config, but plugin logging does not currently change behavior from it. | | useGenAiCompatibilityScope | Legacy compatibility field kept in config code, not surfaced in plugin schema. |

Privacy And Safety Notes

  • captureMessageContent: true is the highest-impact privacy switch.
  • captureToolOutput: true can capture large or sensitive tool results.
  • redactSecrets: true helps, but it is best-effort rather than a formal DLP guarantee.
  • saveHookLogs: true writes raw payloads to local disk. Turn it off after debugging.
  • Prefer LOGFIRE_TOKEN in the shell environment instead of committing tokens into openclaw.json.

Distributed Tracing

When enabled, the plugin injects W3C traceparent into matching command parameters before the tool runs.

{
  "plugins": {
    "entries": {
      "openclaw-logfire": {
        "enabled": true,
        "config": {
          "distributedTracing": {
            "enabled": true,
            "injectIntoCommands": true,
            "urlPatterns": [
              "https://api.example.com/*",
              "http://localhost:8000/*"
            ]
          }
        }
      }
    }
  }
}

Current scope:

  • works for outbound command injection only
  • targets HTTP-like commands such as curl, wget, http, and httpie
  • respects distributedTracing.urlPatterns

Troubleshooting

No traces appear

Check these first:

  1. LOGFIRE_TOKEN is set in the environment seen by OpenClaw.
  2. The plugin entry key is exactly openclaw-logfire.
  3. OpenClaw is at least 2026.2.1.
  4. OpenClaw was restarted after config changes.
  5. Your machine can reach the selected Logfire region endpoint.

Agent spans exist, but chat spans are incomplete

Make sure OpenClaw emits llm_output after the final lastAssistant object is fully assembled. The plugin reconstructs chat phases from the completed assistant payload.

Tool spans do not show failures clearly

Current OpenClaw hook payloads do not always expose tool-level error details at tool_result_persist, so failures may be reflected on the root agent span rather than the individual tool span.

I need raw hook payloads

Temporarily set:

{
  "plugins": {
    "entries": {
      "openclaw-logfire": {
        "enabled": true,
        "config": {
          "saveHookLogs": true
        }
      }
    }
  }
}

This writes hook payloads to ~/.openclaw/logs/.

Local Development

git clone https://github.com/chenbaiyujason/openclaw-logfire
cd openclaw-logfire
npm install
npm run build
npm run typecheck
npm test

To load the local checkout in OpenClaw, either symlink it into your extensions directory or add the repo path to plugins.load.paths.

ln -s "$(pwd)" ~/.openclaw/extensions/openclaw-logfire

Or:

{
  "plugins": {
    "load": {
      "paths": [
        "/absolute/path/to/openclaw-logfire"
      ]
    }
  }
}

Then export LOGFIRE_TOKEN, restart OpenClaw, and verify with:

openclaw plugins list

License

MIT