You need stable event names and payload semantics across strategies, runtime, and tooling.
After this guide, you can add signals without namespace drift.
Canonical Signal Names
Signal names are stable string contracts:
- strategy queries:
ai.react.query,ai.cod.query,ai.cot.query,ai.aot.query,ai.tot.query,ai.got.query,ai.trm.query,ai.adaptive.query - plugin strategy runs:
reasoning.cod.run,reasoning.cot.run,reasoning.aot.run,reasoning.tot.run,reasoning.got.run,reasoning.trm.run,reasoning.adaptive.run - runtime emitted signals:
ai.request.started,ai.request.completed,ai.request.failed,ai.request.error,ai.llm.response,ai.llm.delta,ai.tool.started,ai.tool.result,ai.embed.result,ai.usage,ai.react.worker.event
ReAct worker control/internal runtime signals (for worker orchestration) are separate from the public contracts above:
ai.react.worker.start, ai.react.worker.cancel, ai.react.worker.runtime.event, ai.react.worker.runtime.done, ai.react.worker.runtime.failed.
Signal Modules
Typed signal modules define payload contracts and canonical signal types:
Jido.AI.Signal.RequestStarted->ai.request.startedJido.AI.Signal.RequestCompleted->ai.request.completedJido.AI.Signal.RequestFailed->ai.request.failedJido.AI.Signal.RequestError->ai.request.errorJido.AI.Signal.LLMResponse->ai.llm.responseJido.AI.Signal.LLMDelta->ai.llm.deltaJido.AI.Signal.ToolStarted->ai.tool.startedJido.AI.Signal.ToolResult->ai.tool.resultJido.AI.Signal.EmbedResult->ai.embed.resultJido.AI.Signal.Usage->ai.usageJido.AI.Reasoning.ReAct.Signal->ai.react.worker.event
Lifecycle Notes
ai.llm.deltacarries incremental model text. Runtime-backed strategies may include optional ordering and correlation fields (seq,request_id,run_id,iteration). Consumers that need exact transcript reconstruction should order deltas byseqwithin the samecall_idwhen it is present; delivery order alone is not a durable ordering contract.ai.tool.startedis the public start-of-execution contract for tool-capable runtimes.ai.tool.resultis the terminal contract for both success and failure.ai.request.started,ai.request.completed, andai.request.failedare expected across reasoning strategies, including AoT, CoT/CoD, GoT, ReAct, ToT, and TRM.
Metadata Contract
The public signal payload remains the primary contract. Some signals also carry
optional metadata maps for runtime correlation and observability:
ai.llm.response.metadataai.llm.delta.metadataai.tool.started.metadataai.tool.result.metadataai.usage.metadata
Common metadata keys:
request_idrun_iditerationorigin(:directive,:action,:worker_runtime)operation(:chat,:complete,:generate_object,:stream_text,:generate_text,:embed,:tool_execute)strategy
These fields are additive. Consumers must tolerate missing keys.
Example: Emit Standard Request Error
sig = Jido.AI.Signal.RequestError.new!(%{
request_id: "req-1",
reason: :busy,
message: "Agent is processing another request"
})Failure Mode: Namespace Drift
Symptom:
- strategy route never fires
Fix:
- use canonical signal strings consistently everywhere signals are created
- keep
signal_routes/1aligned with canonical names
Defaults You Should Know
- canonical list lives in module type declarations (
Jido.AI.Signal.*) and strategy/plugin route declarations (signal_routes/1, pluginsignal_types/0) - signal payload schemas should remain backward compatible when possible
- runtime event envelopes are strategy-agnostic via
Jido.AI.Runtime.Event;Jido.AI.Reasoning.ReAct.Eventremains a compatibility wrapper
When To Use / Not Use
Use this guide when:
- adding or renaming signal types
- integrating external handlers for telemetry or routing
Do not use this guide when:
- changes are internal and do not alter signal contracts