PtcRunner.Lisp.Eval.Context (PtcRunner v0.9.0)

Copy Markdown View Source

Evaluation context for the Lisp interpreter.

Bundles the parameters that flow through recursive evaluation:

  • ctx: External data (read-only)
  • user_ns: User namespace (mutable bindings from def)
  • env: Lexical environment (variable bindings)
  • tool_exec: Tool executor function
  • turn_history: Previous turn results for multi-turn loops

Limits

FieldDefaultHard CapPurpose
loop_limit1,00010,000Max loop/recursion iterations
max_print_length2,000Max chars per println call
pmap_max_concurrencyschedulers * 2Max concurrent pmap/pcalls tasks

Summary

Types

Parallel map/calls execution record for tracing.

t()

Tool call record for tracing.

Trace context for nested agent execution tracing.

Functions

Appends a pmap/pcalls execution record to the context.

Appends a print message to the context.

Appends a tool call record to the context.

Checks whether the tool call limit has been reached.

Increments the iteration count and checks against the limit.

Merges two contexts, specifically combining prints, tool calls, and pmap calls. Used to merge results from parallel execution branches (pmap, pcalls).

Merges new bindings into the environment.

Sets a new loop limit, respecting the hard maximum.

Updates the user namespace in the context.

Types

pmap_call()

@type pmap_call() :: %{
  type: :pmap | :pcalls,
  count: non_neg_integer(),
  child_trace_ids: [String.t()],
  child_steps: [any()],
  timestamp: DateTime.t(),
  duration_ms: non_neg_integer(),
  success_count: non_neg_integer(),
  error_count: non_neg_integer()
}

Parallel map/calls execution record for tracing.

Fields:

  • type: :pmap or :pcalls
  • count: Number of parallel tasks
  • child_trace_ids: List of trace IDs from SubAgentTool executions
  • timestamp: When execution started
  • duration_ms: Total execution time
  • success_count: Number of successful executions
  • error_count: Number of failed executions

t()

@type t() :: %PtcRunner.Lisp.Eval.Context{
  budget: map() | nil,
  ctx: map(),
  env: map(),
  iteration_count: integer(),
  journal: map() | nil,
  loop_limit: integer(),
  max_print_length: pos_integer(),
  max_tool_calls: pos_integer() | nil,
  pmap_calls: [pmap_call()],
  pmap_max_concurrency: pos_integer(),
  pmap_timeout: pos_integer(),
  prints: [String.t()],
  summaries: %{required(String.t()) => String.t()},
  tool_cache: map(),
  tool_calls: [tool_call()],
  tool_exec: (String.t(), map() -> term()),
  tools_meta: %{required(String.t()) => %{cache: boolean()}},
  trace_context: trace_context(),
  turn_history: list(),
  user_ns: map()
}

tool_call()

@type tool_call() :: %{
  :name => String.t(),
  :args => map(),
  :result => term(),
  :error => String.t() | nil,
  :timestamp => DateTime.t(),
  :duration_ms => non_neg_integer(),
  optional(:child_trace_id) => String.t(),
  optional(:child_step) => term(),
  optional(:cached) => boolean()
}

Tool call record for tracing.

Fields:

  • name: Tool name
  • args: Arguments passed to tool
  • result: Tool result
  • error: Error message if tool failed
  • timestamp: When tool was called
  • duration_ms: How long tool took
  • child_trace_id: Trace ID of nested SubAgentTool execution (if any)

trace_context()

@type trace_context() ::
  %{
    trace_id: String.t(),
    parent_span_id: String.t() | nil,
    depth: non_neg_integer()
  }
  | nil

Trace context for nested agent execution tracing.

Fields:

  • trace_id: Unique identifier for this trace session
  • parent_span_id: Span ID of the parent operation (nil for root)
  • depth: Nesting depth for visualization

Functions

append_pmap_call(context, pmap_call)

@spec append_pmap_call(t(), pmap_call()) :: t()

Appends a pmap/pcalls execution record to the context.

append_print(context, message)

@spec append_print(t(), String.t()) :: t()

Appends a print message to the context.

Long messages are truncated to max_print_length characters (default: 2000).

append_tool_call(context, tool_call)

@spec append_tool_call(t(), tool_call()) :: t()

Appends a tool call record to the context.

check_tool_call_limit(map)

@spec check_tool_call_limit(t()) :: :ok | {:error, :tool_call_limit_exceeded}

Checks whether the tool call limit has been reached.

Returns :ok when unlimited (nil) or under the limit, {:error, :tool_call_limit_exceeded} when at or over.

increment_iteration(context)

@spec increment_iteration(t()) :: {:ok, t()} | {:error, :loop_limit_exceeded}

Increments the iteration count and checks against the limit.

merge(ctx1, ctx2)

@spec merge(t(), t()) :: t()

Merges two contexts, specifically combining prints, tool calls, and pmap calls. Used to merge results from parallel execution branches (pmap, pcalls).

merge_env(context, bindings)

@spec merge_env(t(), map()) :: t()

Merges new bindings into the environment.

new(ctx, user_ns, env, tool_exec, turn_history, opts \\ [])

@spec new(map(), map(), map(), (String.t(), map() -> term()), list(), keyword()) ::
  t()

Creates a new evaluation context.

Options

  • :max_print_length - Max characters per println call (default: 2000)
  • :budget - Budget info map for (budget/remaining) introspection (default: nil)
  • :pmap_timeout - Timeout in ms for each pmap task (default: 5000). Increase for LLM-backed tools.
  • :pmap_max_concurrency - Max concurrent tasks in pmap/pcalls (default: System.schedulers_online() * 2)
  • :trace_context - Trace context for nested agent tracing (default: nil)

Examples

iex> ctx = PtcRunner.Lisp.Eval.Context.new(%{}, %{}, %{}, fn _, _ -> nil end, [])
iex> ctx.user_ns
%{}

iex> ctx = PtcRunner.Lisp.Eval.Context.new(%{}, %{}, %{}, fn _, _ -> nil end, [], max_print_length: 500)
iex> ctx.max_print_length
500

iex> ctx = PtcRunner.Lisp.Eval.Context.new(%{}, %{}, %{}, fn _, _ -> nil end, [], budget: %{turns: 10})
iex> ctx.budget
%{turns: 10}

iex> ctx = PtcRunner.Lisp.Eval.Context.new(%{}, %{}, %{}, fn _, _ -> nil end, [], pmap_timeout: 60_000)
iex> ctx.pmap_timeout
60000

set_loop_limit(context, new_limit)

@spec set_loop_limit(t(), integer()) :: t()

Sets a new loop limit, respecting the hard maximum.

update_user_ns(context, new_user_ns)

@spec update_user_ns(t(), map()) :: t()

Updates the user namespace in the context.