Frozen contract reference: see docs/event-contract-v1.md for the stable v1 wire-format specification. This document remains the higher-level routing and migration guide.
This document is the clawhip-side normalization contract for native OMC/OMX operational events.
clawhip should be the single routing and formatting layer. OMC/OMX should emit machine-readable native events, not send direct Slack/Discord notifications.
Prefer routing on these canonical clawhip events:
session.startedsession.blockedsession.finishedsession.failedsession.retry-neededsession.pr-createdsession.test-startedsession.test-finishedsession.test-failedsession.handoff-needed
For backward compatibility, clawhip still accepts legacy local wrapper emits:
agent.startedagent.blockedagent.finishedagent.failed
agent.started|blocked|finished|failed and session.started|blocked|finished|failed intentionally cross-match in routing so existing configs do not break.
clawhip normalizes already-merged OMC/OMX payloads from these upstream surfaces:
- OMC payloads that include
signal.routeKey - OMX payloads that include
context.normalized_event - native OMX hook-envelope CLI ingress via
clawhip omx hook - native OMX hook-envelope POSTs to clawhip's
/api/omx/hook//omx/hookingress - legacy local
clawhip emit agent.* ...wrapper emits fromskills/omc/create.shandskills/omx/create.sh
Not every upstream raw event becomes a canonical session event. Low-signal/raw hook events should stay as secondary/debug inputs. New routes should target session.*.
In particular, raw OMX hook events such as pre-tool-use / post-tool-use are not clawhip v1 canonical route keys. When OMX wants clawhip-native routing for tool activity, it should map the activity onto an existing v1 event family (session.failed, session.test-*, session.pr-created, etc.) and keep tool details in metadata like command, tool_name, and error_summary.
When upstream provides it, clawhip normalizes these fields onto the top-level payload:
toolsession_namesession_idrepo_namerepo_pathworktree_pathbranchissue_numberpr_numberpr_urlcommandtool_nametest_runnerstatussummaryerror_messageevent_timestampraw_eventcontract_event
toolis normalized toomcoromxwhen clawhip can infer it.statusis backfilled for legacyagent.*emits so genericclawhip emit agent.finished --agent omx ...remains valid.- OMC
context.projectNamebackfills both compatibilityprojectand canonicalrepo_name. - OMC
context.projectPathbackfillsrepo_pathandworktree_pathwhen no more specific path fields are present. issue_numbermay be inferred from session/worktree/branch names likeissue-65when upstream did not send it explicitly.pr_numbermay be inferred frompr_url.raw_eventis retained only when clawhip had to rename the incoming event.contract_eventis the canonical normalized event after clawhip ingestion.- raw OMX tool events such as
pre-tool-use/post-tool-useare not new clawhip v1 canonical events; map them to the frozensession.*family via metadata when they represent PR/test/failure/handoff semantics.
| Upstream signal | Canonical clawhip event |
|---|---|
session.started |
session.started |
session.finished |
session.finished |
session.idle |
session.blocked |
question.requested |
session.blocked |
test.started |
session.test-started |
test.finished |
session.test-finished |
test.failed |
session.test-failed |
pull-request.created |
session.pr-created |
pull-request.failed |
session.failed |
tool.failed |
session.failed |
| Upstream normalized event | Canonical clawhip event |
|---|---|
started |
session.started |
blocked |
session.blocked |
finished |
session.finished |
failed |
session.failed |
retry-needed |
session.retry-needed |
pr-created |
session.pr-created |
test-started |
session.test-started |
test-finished |
session.test-finished |
test-failed |
session.test-failed |
handoff-needed |
session.handoff-needed |
Recommended route filters:
[[routes]]
event = "session.*"
filter = { tool = "omx", repo_name = "clawhip" }
channel = "1480171113253175356"
format = "compact"Prefer filters on structured metadata such as:
toolrepo_namesession_nameissue_numberpr_numberbranch
Avoid routing on rendered message text.
For native OMC/OMX routing, treat these as the non-negotiable defaults:
- route native session traffic on
session.*first; keepagent.*only for compatibility with older local wrapper emits - filter native session traffic on
repo_name, notrepo - if you also filter by tool, use
tool = "omx"ortool = "omc" - if a native session route misses and
[defaults].channelis configured, clawhip can still deliver to that default channel; wrong-channel delivery usually means route mismatch, not transport failure
repo is still common on git/GitHub payloads, but the native OMC/OMX normalization contract promotes repo_name onto the top-level session payload. That is why a route like filter = { tool = "omx", repo = "clawhip" } can keep matching GitHub/git events while missing native session traffic.
Default clawhip session formatting is intentionally low-noise:
- compact: stable one-line status plus the most useful metadata
- inline: dense channel-safe summaries for busy rooms
- alert: same content with alert prefix for high-priority channels
- raw: original normalized payload for debugging
This contract is designed so real-world routing can stay stable even if OMC/OMX keep evolving their internal raw hook/event names.
Direct platform notifications from inside OMC/OMX are deprecated for clawhip-integrated setups.
Preferred model:
- OMC/OMX emit native operational events
- clawhip ingests them directly (for OMX,
clawhip omx hookand/api/omx/hookare the native ingress surfaces) - clawhip normalizes them
- clawhip owns channel routing, mentions, formatting, and webhook delivery
That keeps notification policy in one place and avoids duplicate/noisy Discord or Slack messages.