BEAM-native Avatar actor with typed actions and bounded tool execution.
Avatar asks a typed actor predictor for one action per turn. Tool results,
including policy denials and execution errors, become structured observations
for the next turn. A reserved Finish action or iteration exhaustion invokes
a separate typed finalizer for the task signature.
Each tool callback runs in its own unlinked task, bounded by
:tool_timeout_ms (default 30 seconds), that takes no place in the task
pool. The task carries the caller's settings, Imp.Run context and
Imp.Deadline, and ends when the caller does, so a tool stops when its
caller is killed, when its run is cancelled and when the run's owner dies.
A tool that crashes, or whose task exits, is an observation, not the
caller's crash. When the caller works on a place in the pool, a stream of
Imp tasks the tool enumerates (Imp.Predict.Parallel.map/3,
Imp.Evaluate.run/2) runs on that place, one item at a time; an
Imp.Tasks.async/1 the tool starts itself waits for a place of its own, so
with a full pool it waits until the tool times out. A timeout kills the task, records a terminal action
observation and proceeds directly to finalization. A timed-out call and one
whose task exited read as :unknown in Imp.Tool.outcome/1, since the
tool may have acted.
Inside a run, each tool call is recorded as a :tool_call event and a
:tool_result event whose metadata.outcome says how it ended. Avatar does
not ask a run's :authorize callback, so a run started with one refuses an
Avatar program ({:execution_capability_unsupported, Imp.Predict.Avatar, :authorization}).