Behaviour for post-turn reflection in Planck.Agent.
Implement this behaviour in a sidecar module to inspect completed turns and take action — for example, writing a skill when a complex repeatable workflow is detected.
Behaviour
Use use Planck.Agent.Hooks.TurnEnd and override reflect/2:
defmodule MySidecar.SkillReflector do
use Planck.Agent.Hooks.TurnEnd
@tool_threshold 5
@impl true
def reflect(agent_id, turn_messages) do
# The implementation decides whether to act (e.g. threshold check).
# Signal back via `Planck.Agent.inject_tool_result/3` if a skill was written.
:ok
end
endDispatch
Planck.Agent fires reflect/4 in a background Task after every :turn_end
broadcast:
Hooks.TurnEnd.reflect(state.turn_end_hook, state.id, turn_messages, state.sidecar_node)module: nil— no-op.sidecar_node: nil— callsmodule.reflect/2in-process.sidecar_nodeset — calls via RPC; logs a warning on:badrpc.
The default RPC timeout is 30000 ms; override reflect_timeout/0
to declare a custom expected latency.
Summary
Callbacks
Inspect the completed turn and take action.
RPC call timeout in milliseconds when this hook is invoked remotely.
Functions
Default RPC timeout used when a module omits reflect_timeout/0.
Fire reflection for the completed turn.
Callbacks
@callback reflect( agent_id :: String.t(), turn_messages :: [Planck.Agent.Message.t()] ) :: :ok
Inspect the completed turn and take action.
Called after every turn. The implementation is responsible for any threshold
checks or filtering. Must return :ok.
@callback reflect_timeout() :: pos_integer()
RPC call timeout in milliseconds when this hook is invoked remotely.
Defaults to 30,000 ms.
Functions
@spec default_timeout() :: pos_integer()
Default RPC timeout used when a module omits reflect_timeout/0.
@spec reflect(module() | nil, String.t(), [Planck.Agent.Message.t()], atom() | nil) :: :ok
Fire reflection for the completed turn.
Returns :ok immediately when module is nil. Otherwise dispatches
module.reflect/2 locally or via RPC.