Packages

AI agent framework for Elixir built on OTP. TEA-based agents with crash isolation, inter-agent messaging, team supervision, and real SSE streaming to Anthropic, OpenAI, Ollama, and more.

Current section

Files

Jump to
raxol_agent lib raxol agent sandbox async.ex
Raw

lib/raxol/agent/sandbox/async.ex

defmodule Raxol.Agent.Sandbox.Async do
@moduledoc """
Async-task isolation dimension for `Raxol.Agent.Sandbox`.
Gates `Raxol.Agent.Directive.Async` directives wholesale: the
async function's body is opaque (a closure) so there's no
payload-based matching. The sandbox is either `allow` (abstain)
or `deny`.
## Constructors
Sandbox.Async.allow()
# abstain; any async task allowed
Sandbox.Async.deny()
# block every async task
When an agent wants finer-grained async controls (rate limiting,
per-task timeout, cancellation), it should use the
`Raxol.Agent.Policy` structs around the operation that *creates*
the async task, not the Sandbox dimension. The Sandbox is the
binary "are async tasks permitted at all" check.
"""
@type mode :: :allow | :deny
@type t :: %__MODULE__{mode: mode()}
@enforce_keys [:mode]
defstruct [:mode]
@doc "Construct an allow-all async sandbox (abstain)."
@spec allow() :: t()
def allow, do: %__MODULE__{mode: :allow}
@doc "Construct a deny-all async sandbox."
@spec deny() :: t()
def deny, do: %__MODULE__{mode: :deny}
@doc "Whether async tasks are permitted by this sandbox."
@spec allowed?(t()) :: boolean()
def allowed?(%__MODULE__{mode: :allow}), do: true
def allowed?(%__MODULE__{mode: :deny}), do: false
end
defimpl Raxol.Agent.Sandbox, for: Raxol.Agent.Sandbox.Async do
alias Raxol.Agent.Sandbox.Async
def authorize(_sandbox, action, _payload, _ctx) when action != :async, do: :ok
def authorize(sandbox, :async, _payload, _ctx) do
if Async.allowed?(sandbox) do
:ok
else
{:deny, :async_denied}
end
end
end