Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b1f7248
Add OpenClaw LLM Observability integration
oldcodeoberyn Mar 19, 2026
e341e3f
Fix elastic-package build validation errors and YAML syntax
oldcodeoberyn Mar 19, 2026
a9dc937
Fix policy_templates input type for deployment mode
oldcodeoberyn Mar 19, 2026
66e91c4
Fix Agent input type from legacy log to logfile (filestream)
oldcodeoberyn Mar 19, 2026
10f02b5
Enhance pipeline: extract tool_calls and clean untrusted metadata fro…
oldcodeoberyn Mar 19, 2026
b561d5b
Extract agent.id and session.id from log file path via grok
oldcodeoberyn Mar 19, 2026
e431c1e
Optimize grok pattern for robust agent.id and session.id extraction
oldcodeoberyn Mar 19, 2026
dcb275d
Fix grok pattern to correctly handle absolute paths prefix
oldcodeoberyn Mar 19, 2026
4b823bf
Fix grok output being overwritten by json processor
oldcodeoberyn Mar 19, 2026
e090acf
Add exported Kibana dashboard, search, and index_pattern objects
oldcodeoberyn Mar 19, 2026
317db3a
feat(openclaw): add integration for session and usage observability
oldcodeoberyn Mar 21, 2026
a67ec03
fix(openclaw): ignore dynamic event.ingested field in pipeline tests
oldcodeoberyn Mar 21, 2026
7f376a9
fix(openclaw): correctly define tool_calls as an object array
oldcodeoberyn Mar 21, 2026
b4870fb
fix(openclaw): change tool_calls.arguments to flattened type to suppo…
oldcodeoberyn Mar 21, 2026
cf0c9c5
chore: remove deploy_openclaw.sh from version control
oldcodeoberyn Mar 21, 2026
897d83e
fix(openclaw): add openclaw package to CODEOWNERS
oldcodeoberyn Mar 21, 2026
256b755
fix(openclaw): add missing docker-compose.yml for dev deploy
oldcodeoberyn Mar 21, 2026
01d2649
fix(openclaw): update package owner in manifest to match CODEOWNERS
oldcodeoberyn Mar 21, 2026
e7eba8c
fix(openclaw): correct icon MIME type to image/png in manifest.yml
oldcodeoberyn Mar 21, 2026
f49fe3a
fix(openclaw): update README.md generated fields documentation to ref…
oldcodeoberyn Mar 21, 2026
7b9c824
fix(openclaw): downgrade Kibana typeMigrationVersion in dashboard fro…
oldcodeoberyn Mar 21, 2026
303cf01
fix(openclaw): remove unsupported showApplySelections field from dash…
oldcodeoberyn Mar 21, 2026
b02dad9
fix(openclaw): remove unsupported sections field from dashboard for K…
oldcodeoberyn Mar 21, 2026
1e14297
chore: trigger CI rebuild for flaky maven connection reset
oldcodeoberyn Mar 22, 2026
2c251bb
docs: fix vale linting errors (remove please, replace see with refer to)
oldcodeoberyn Mar 23, 2026
da73164
fix(openclaw): change text and thinking fields to match_only_text
oldcodeoberyn Mar 23, 2026
24078df
feat: update openclaw package manifest and dashboard
oldcodeoberyn Mar 26, 2026
96dff7f
fix: downgrade Kibana dashboard and search SO versions to 8.9.0 compa…
oldcodeoberyn Mar 26, 2026
53e8f17
fix: remove typeMigrationVersion from Kibana saved objects to fix CI
oldcodeoberyn Mar 27, 2026
ca2b0b1
fix: remove sections/tabs fields from saved objects for Kibana 8.12 c…
oldcodeoberyn Mar 27, 2026
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@
/packages/okta @elastic/security-service-integrations
/packages/openai @elastic/obs-infraobs-integrations
/packages/opencanary @elastic/security-service-integrations
/packages/openclaw @elastic/ecosystem
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Howdy from @elastic/ecosystem - Can we discuss more about the future of this integration and how you're expecting ownership to work here? This is the first we're seeing this and we're on the hook at codeowners here. We don't use or understand OpenClaw enough to be considered subject matter experts and maintain this package.

/packages/oracle @elastic/obs-infraobs-integrations
/packages/oracle_weblogic @elastic/obs-infraobs-integrations
/packages/osquery @elastic/sec-windows-platform
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ elastic-package

# Folder created by the Sonar Scanner
.scannerwork/
deploy_openclaw.sh
23 changes: 23 additions & 0 deletions packages/openclaw/_dev/build/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenClaw Integration

The OpenClaw integration allows you to ingest and monitor LLM observability metrics, session logs, and assistant usage data from the OpenClaw AI agent framework.

It provides a comprehensive view of:
- **Token Consumption**: Input and output tokens used per request.
- **Cost Analysis**: Financial cost incurred per model and session.
- **Tool Usage**: Which tools (skills) were executed and their frequencies.
- **Latency**: End-to-end response time of the AI agent.

## Data Streams

This integration includes the following data streams:

### Sessions Data Stream (`sessions`)

The `sessions` data stream collects detailed, turn-by-turn interactions from OpenClaw, capturing user prompts, agent thoughts, final responses, and internal metadata (like model versions and token counts).

**Exported Fields**

For a detailed list of exported fields, refer to the [ECS Field Reference](https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html) and the specific fields listed below:

{{fields "sessions"}}
5 changes: 5 additions & 0 deletions packages/openclaw/_dev/deploy/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: "3.8"
services:
dummy:
image: busybox
command: ["sleep", "infinity"]
20 changes: 20 additions & 0 deletions packages/openclaw/changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
- version: "1.0.3"
changes:
- description: "Change text and thinking field mapping to match_only_text"
type: "bugfix"
link: "https://github.com/elastic/integrations/pull/17936"
- version: "1.0.2"
changes:
- description: "Fix missing macro expansion in README by moving it to _dev/build/docs/"
type: "bugfix"
link: "https://github.com/elastic/integrations/pull/3"
- version: "1.0.1"
changes:
- description: "Update dashboard fields and refresh deployment"
type: "bugfix"
link: "https://github.com/elastic/integrations/pull/2"
- version: "1.0.0"
changes:
- description: "Initial release"
type: "enhancement"
link: "https://github.com/elastic/integrations/pull/1"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"timestamp":"2026-03-19T02:57:28.310Z","message":{"role":"assistant","model":"gemini-3.1-pro-preview","usage":{"input":13362,"output":437,"totalTokens":13799,"cost":{"total":0.031968}},"content":[{"type":"text","text":"Simulated text"},{"type":"thinking","thinking":"Thinking..."},{"type":"toolCall","name":"weather","arguments":{"city":"London"}}]}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dynamic_fields:
"openclaw.agent.id": ".*"
"openclaw.session.id": ".*"
"event.ingested": ".*"
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"expected": [
{
"@timestamp": "2026-03-19T02:57:28.310Z",
"event": {
"ingested": "2026-03-21T04:33:21.503436214Z"
},
"openclaw": {
"cost": {
"usd": 0.031968
},
"model": "gemini-3.1-pro-preview",
"role": "assistant",
"text": "Simulated text",
"thinking": "Thinking...",
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "weather"
}
],
"usage": {
"input_tokens": 13362,
"output_tokens": 437,
"total_tokens": 13799
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
paths:
{{#each paths}}
- {{this}}
{{/each}}
exclude_files: [".gz$"]
tags:
{{#if tags}}
{{#each tags}}
- {{this}}
{{/each}}
{{/if}}
{{#contains "forwarded" tags}}
publisher_pipeline.disable_host: true
{{/contains}}
processors:
- add_locale: ~
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
description: Pipeline for parsing OpenClaw session JSONL logs
processors:
- set:
field: event.ingested
value: '{{_ingest.timestamp}}'
- json:
field: message
target_field: openclaw
ignore_failure: true
- grok:
field: log.file.path
patterns:
- '%{GREEDYDATA}/agents/(?<openclaw.agent.id>[^/]+)/sessions/(?<openclaw.session.id>[^/]+)\.jsonl$'
ignore_missing: true
ignore_failure: true
- date:
if: ctx?.openclaw?.timestamp != null
field: openclaw.timestamp
target_field: "@timestamp"
formats:
- ISO8601
- rename:
field: openclaw.message.role
target_field: openclaw.role
ignore_missing: true
- rename:
field: openclaw.message.model
target_field: openclaw.model
ignore_missing: true
- rename:
field: openclaw.message.usage.input
target_field: openclaw.usage.input_tokens
ignore_missing: true
- rename:
field: openclaw.message.usage.output
target_field: openclaw.usage.output_tokens
ignore_missing: true
- rename:
field: openclaw.message.usage.totalTokens
target_field: openclaw.usage.total_tokens
ignore_missing: true
- rename:
field: openclaw.message.usage.cost.total
target_field: openclaw.cost.usd
ignore_missing: true
- script:
description: "Extract text, thinking, and tool_calls from content array"
lang: painless
if: "ctx.openclaw?.message?.content != null"
source: |
def content = ctx.openclaw.message.content;
if (content instanceof List) {
def tool_calls = [];
for (def item : content) {
if (item.type == 'text' && item.text != null) {
ctx.openclaw.text = item.text;
} else if (item.type == 'thinking' && item.thinking != null) {
ctx.openclaw.thinking = item.thinking;
} else if (item.type == 'toolCall') {
def tc = new HashMap();
if (item.name != null) {
tc.put('name', item.name);
}
if (item.arguments != null) {
tc.put('arguments', item.arguments);
}
tool_calls.add(tc);
}
}
if (tool_calls.size() > 0) {
ctx.openclaw.tool_calls = tool_calls;
}
} else if (content instanceof String) {
ctx.openclaw.text = content;
}
- remove:
field:
- message
- openclaw.message
- openclaw.timestamp
ignore_missing: true
on_failure:
- set:
field: error.message
value: "{{ _ingest.on_failure_message }}"
12 changes: 12 additions & 0 deletions packages/openclaw/data_stream/sessions/fields/base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
- name: "@timestamp"
type: date
description: Event timestamp.
- name: data_stream.type
type: constant_keyword
description: Data stream type.
- name: data_stream.dataset
type: constant_keyword
description: Data stream dataset.
- name: data_stream.namespace
type: constant_keyword
description: Data stream namespace.
43 changes: 43 additions & 0 deletions packages/openclaw/data_stream/sessions/fields/fields.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
- name: openclaw
type: group
fields:
- name: cost.usd
type: float
description: Cost in USD
- name: model
type: keyword
description: Model name
- name: role
type: keyword
description: Role of the message sender (user or assistant)
- name: text
type: match_only_text
description: Text content of the interaction
- name: thinking
type: match_only_text
description: Internal thinking process
- name: tool_calls
type: group
description: Tool calls invoked during the session
fields:
- name: name
type: keyword
description: Name of the tool called
- name: arguments
type: flattened
description: Arguments passed to the tool
- name: usage.input_tokens
type: long
description: Number of input tokens
- name: usage.output_tokens
type: long
description: Number of output tokens
- name: usage.total_tokens
type: long
description: Total token usage
- name: agent.id
type: keyword
description: Agent ID
- name: session.id
type: keyword
description: Session ID
16 changes: 16 additions & 0 deletions packages/openclaw/data_stream/sessions/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type: logs
title: OpenClaw Sessions
release: beta
streams:
- input: logfile
title: OpenClaw Session Logs
description: Collects OpenClaw JSONL session files
vars:
- name: paths
type: text
title: Paths
multi: true
required: true
show_user: true
default:
- ~/.openclaw/agents/*/sessions/*.jsonl*
Comment on lines +15 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High sessions/manifest.yml:15

The default path ~/.openclaw/agents/*/sessions/*.jsonl* uses tilde expansion, which Filebeat does not support — the ~ is interpreted literally as a directory named ~, so the integration fails to collect any logs by default. Consider using an absolute path pattern like /home/*/.openclaw/agents/*/sessions/*.jsonl* or a platform-appropriate alternative.

         default:
-          - ~/.openclaw/agents/*/sessions/*.jsonl*
+          - /home/*/.openclaw/agents/*/sessions/*.jsonl*
🤖 Copy this AI Prompt to have your agent fix this:
In file packages/openclaw/data_stream/sessions/manifest.yml around lines 15-16:

The default path `~/.openclaw/agents/*/sessions/*.jsonl*` uses tilde expansion, which Filebeat does not support — the `~` is interpreted literally as a directory named `~`, so the integration fails to collect any logs by default. Consider using an absolute path pattern like `/home/*/.openclaw/agents/*/sessions/*.jsonl*` or a platform-appropriate alternative.

43 changes: 43 additions & 0 deletions packages/openclaw/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# OpenClaw Integration

The OpenClaw integration allows you to ingest and monitor LLM observability metrics, session logs, and assistant usage data from the OpenClaw AI agent framework.

It provides a comprehensive view of:
- **Token Consumption**: Input and output tokens used per request.
- **Cost Analysis**: Financial cost incurred per model and session.
- **Tool Usage**: Which tools (skills) were executed and their frequencies.
- **Latency**: End-to-end response time of the AI agent.

## Data Streams

This integration includes the following data streams:

### Sessions Data Stream (`sessions`)

The `sessions` data stream collects detailed, turn-by-turn interactions from OpenClaw, capturing user prompts, agent thoughts, final responses, and internal metadata (like model versions and token counts).

**Exported Fields**

For a detailed list of exported fields, refer to the [ECS Field Reference](https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html) and the specific fields listed below:

**Exported fields**

| Field | Description | Type |
|---|---|---|
| @timestamp | Event timestamp. | date |
| data_stream.dataset | Data stream dataset. | constant_keyword |
| data_stream.namespace | Data stream namespace. | constant_keyword |
| data_stream.type | Data stream type. | constant_keyword |
| openclaw.agent.id | Agent ID | keyword |
| openclaw.cost.usd | Cost in USD | float |
| openclaw.model | Model name | keyword |
| openclaw.role | Role of the message sender (user or assistant) | keyword |
| openclaw.session.id | Session ID | keyword |
| openclaw.text | Text content of the interaction | match_only_text |
| openclaw.thinking | Internal thinking process | match_only_text |
| openclaw.tool_calls.arguments | Arguments passed to the tool | flattened |
| openclaw.tool_calls.name | Name of the tool called | keyword |
| openclaw.usage.input_tokens | Number of input tokens | long |
| openclaw.usage.output_tokens | Number of output tokens | long |
| openclaw.usage.total_tokens | Total token usage | long |

Binary file added packages/openclaw/img/openclaw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading