Event log
Queryable structured events for agents. Module: mechaharness.core.events.
Stability: evolving. AbstractHarness.run() (including pass_through,
tool_loop, and react) emits lifecycle, inference, tool, access, and cost
records. Hosts can also emit / query directly.
Surface
Item |
Value |
|---|---|
Module |
|
Logger |
|
Stability |
evolving |
Envelope
Every record is an Event:
Field |
Meaning |
|---|---|
|
UTC timestamp |
|
Wire key |
|
Agent / harness instance |
|
Optional parent agent |
|
One run lifecycle |
|
JSON object (no API keys) |
Event.type is a string. Pass an EventType subclass or a namespace:name
string when constructing; both store the same key. Unknown keys are valid as
long as they are namespaced. Bare names (run_start) are rejected.
Event types
EventType is a class hierarchy, not an enum. Intermediate classes set
namespace; leaves set name. Built-in types subclass CoreEvent
(namespace = "core"):
Class |
Wire key |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core:access_check payload: tool, required, granted, allowed.
core:cost may include prompt_tokens / completion_tokens / total_tokens.
core:inference may include reasoning_content and usage. Hosts add types by
subclassing without editing this module:
from mechaharness.core.events import EventType
class WidgetDone(EventType):
namespace = "acme"
name = "widget"
assert WidgetDone.key() == "acme:widget"
EventType.parse("core:run_start") returns the registered class. Unregistered
keys still round-trip on Event.type; parse raises KeyError for those.
EventLog
class EventLog:
def emit(self, event: Event) -> None: ...
def query(
self,
*,
agent_id: str | None = None,
run_id: str | None = None,
descendants: bool = False,
types: Sequence[str | type[EventType]] | None = None,
) -> list[Event]: ...
def agents(self, *, parent_id: str | None = None) -> list[AgentRef]: ...
query(agent_id=..., descendants=True) returns that agent plus children
linked by parent_agent_id. agents(parent_id=...) lists direct children.
types= accepts classes or wire keys.
Implementations
InMemoryEventLog— store used for tests and parent queries.LoggingEventLog— one JSON line peremiton loggermechaharness.events.query/agentsreturn empty lists (write adapter only).FanoutEventLog(*logs)—emitto every log;query/agentsuse the first non-logging store.default_event_log()— fan-out of in-memory + logging.
from mechaharness.core.events import Event, InMemoryEventLog, RunStart
log = InMemoryEventLog()
log.emit(
Event(
type=RunStart,
agent_id="agent-1",
run_id="run-1",
payload={"prompt_chars": 12},
)
)
assert log.query(agent_id="agent-1")[0].type == "core:run_start"