# `Nous.RunContext`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/run_context.ex#L1)

Context passed to tools and dynamic prompts during agent execution.

The RunContext provides access to:
- Dependencies (deps) - User-provided data like database connections
- Retry count - Number of times this tool has been retried
- Usage information - Token and request counts so far

## Example with Tool

    defmodule MyTools do
      def search_database(ctx, query) do
        # Access database from dependencies
        ctx.deps.database
        |> Database.search(query)
        |> format_results()
      end
    end

    # Pass deps when running agent
    deps = %{database: MyApp.Database}
    {:ok, result} = Agent.run(agent, "Search for users", deps: deps)

The struct itself is plain data — build one directly to call a tool
outside the agent loop, or to assert on what a tool would see:

    iex> ctx = RunContext.new(%{database: MyApp.Database, api_key: "secret"})
    iex> ctx.deps.api_key
    "secret"
    iex> {ctx.retry, ctx.approval_gated?, ctx.usage.total_tokens}
    {0, false, 0}

# `approval_decision`

```elixir
@type approval_decision() :: :approve | :reject | {:edit, map()}
```

Decision returned by an approval handler for a single tool call.

# `approval_handler`

```elixir
@type approval_handler() :: (map() -&gt; approval_decision())
```

Called before an approval-gated tool runs. Receives the same
`%{name:, id:, arguments:, tool:}` shape the agent runner passes its handler,
so one handler works for both entry points (`id` is nil outside the runner,
which is the only place a provider tool-call id exists).

# `t`

```elixir
@type t() :: t(any())
```

# `t`

```elixir
@type t(deps) :: %Nous.RunContext{
  approval_gated?: boolean(),
  approval_handler: approval_handler() | nil,
  deps: deps,
  retry: non_neg_integer(),
  sandbox: Nous.Sandbox.Policy.t() | nil,
  usage: Nous.Usage.t()
}
```

# `new`

```elixir
@spec new(deps :: any(), opts :: keyword()) :: t(any())
```

Create a new run context with dependencies.

## Options

  * `:retry` - Current retry count (default: 0)
  * `:usage` - Current usage information (default: empty Usage)
  * `:approval_handler` - Called before a tool with `requires_approval: true`
    runs. Without one, such tools are rejected (see `Nous.ToolExecutor`).
  * `:approval_gated?` - Set by a caller that has ALREADY run its own
    approval pipeline (the agent runner does), so `Nous.ToolExecutor` does
    not prompt a second time. Defaults to `false` — i.e. ungated.
  * `:sandbox` - Optional `Nous.Sandbox.Policy` for this session. Tools that
    spawn subprocesses pass the context to `Nous.Sandbox.Policy.resolve/2`,
    which treats this field as the session-level override: it wins over
    `deps[:workspace_root]` and over the `:sandbox_mode` application setting.
    `nil` (the default) means unset — resolution falls back to app config.

## Examples

    iex> ctx = RunContext.new(%{database: MyApp.Database, api_key: "secret"})
    iex> ctx.deps.database
    MyApp.Database

An approval-gated context carries the handler the tool executor consults
before running a `requires_approval: true` tool:

    iex> handler = fn %{name: name} -> if name == "delete_all", do: :reject, else: :approve end
    iex> ctx = RunContext.new(%{}, retry: 2, approval_handler: handler)
    iex> {ctx.retry, ctx.approval_handler.(%{name: "delete_all"}), ctx.approval_gated?}
    {2, :reject, false}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
