DEV Community

Mukunda Rao Katta
Mukunda Rao Katta

Posted on

grep for your agent traces — substring, exact, and regex in one call

Hermes Agent Challenge Submission: Build With Hermes Agent

This is a submission for the Hermes Agent Challenge.

After a 50-task literature review run I had 3,000 JSONL events. I wanted the tool calls that had errors. Then I wanted only the llm_call events from the supervisor lane. Then the events whose name matched ^web_. Every time I reached for a new filter I was writing a new list comprehension.

That's trace-grep.

One call

from trace_grep import grep_events, grep_file, grep_text, grep_field

events = load_my_events()

# Full-text search across all fields
matches = grep_text(events, "timeout")

# Exact field match
matches = grep_field(events, "kind", "tool_call")

# Substring match in a specific field
matches = grep_field(events, "name", contains="search")

# Regex match
matches = grep_field(events, "name", regex=r"^web_")

# Has error
matches = grep_events(events, has_error=True)

# Invert (find non-matching events)
matches = grep_field(events, "kind", "tool_call", invert=True)
Enter fullscreen mode Exit fullscreen mode

From a file

from trace_grep import grep_file

matches = grep_file("logs/run.jsonl", pattern="error", has_error=True)
Enter fullscreen mode Exit fullscreen mode

Combine criteria (AND)

Every argument you pass becomes another filter. All must match.

matches = grep_events(
    events,
    field="kind", value="tool_call",
    has_error=True,
)
# tool calls that also have an error field
Enter fullscreen mode Exit fullscreen mode

GrepMatch

Every result is a GrepMatch — the full event, its original index, and which fields matched:

@dataclass
class GrepMatch:
    event: dict          # the full event
    index: int           # 0-based position in the input list
    matched_fields: dict # {field: value} for matched fields
Enter fullscreen mode Exit fullscreen mode

So you can still read every field on the original event, and you know exactly where it came from.

error detection

has_error=True checks for any of error, err, or exception — covers the naming differences across agent frameworks:

# find everything that failed
failures = grep_events(events, has_error=True)
for m in failures:
    print(m.event.get("name"), m.event.get("error"))
Enter fullscreen mode Exit fullscreen mode

has_error=False returns events without any error field — useful to confirm the happy path.

What I actually do with it

# How many tool calls errored?
errors = grep_events(events, field="kind", value="tool_call", has_error=True)

# Which web tools fired?
web_tools = grep_field(events, "name", regex=r"^web_")

# Everything NOT from the supervisor lane
workers = grep_field(events, "lane", regex=r"worker-\d+")

# Cost events only — exact float match
expensive = grep_events(events, field="cost_usd", value=0.05)
Enter fullscreen mode Exit fullscreen mode

No custom parser needed per filter.

Zero dependencies

Standard library only: re, json, pathlib, dataclasses. Nothing to install beyond the package.

pip install trace-grep
Enter fullscreen mode Exit fullscreen mode

Repo: https://github.com/MukundaKatta/trace-grep

Top comments (0)