# `ADK.ToolContext`
[🔗](https://github.com/zeroasterisk/adk-elixir/blob/main/lib/adk/tool_context.ex#L1)

Context passed to tool execution, providing access to session state,
artifacts, credentials, and agent transfer capabilities.

Mirrors Python ADK's unified `Context` (formerly `ToolContext`) — tools
receive this struct and use its functions to interact with the runtime.

## Capabilities

- **Session state** — `get_state/3`, `put_state/3` for reading/writing session state
- **Artifacts** — `save_artifact/4`, `load_artifact/3`, `list_artifacts/1` for file/blob storage
- **Credentials** — `request_credential/2`, `load_credential/2`, `save_credential/2`
- **Agent transfer** — `transfer_to_agent/2` to hand off to another agent
- **Event actions** — `actions/1` to access the mutable event actions (state/artifact deltas)

# `t`

```elixir
@type t() :: %ADK.ToolContext{
  actions: ADK.EventActions.t(),
  context: ADK.Context.t(),
  function_call_id: String.t(),
  tool_def: map() | nil,
  tool_name: String.t()
}
```

# `actions`

```elixir
@spec actions(t()) :: ADK.EventActions.t()
```

Get the event actions (state deltas, artifact deltas, auth requests).

# `get_credential`

```elixir
@spec get_credential(t(), String.t(), ADK.Auth.Credential.t(), keyword()) ::
  {:ok, ADK.Auth.Credential.t()} | :needs_auth | {:error, term()}
```

Get a ready-to-use credential, running OAuth2 exchange or refresh as needed.

This is the recommended way to obtain credentials in tool implementations.
It uses `ADK.Auth.CredentialManager` to orchestrate the full lifecycle:

1. Simple credentials (api_key, http_bearer) → returned immediately
2. Stored credential → refreshed if near-expiry, returned
3. Auth-code credential → exchanged for tokens, stored, returned
4. Client-credentials capable → exchanges automatically, returned
5. No stored + no way to get one → returns `:needs_auth`

When `:needs_auth` is returned, call `request_credential/2` to signal to the
runner that user authentication is required.

## Example

    def run(tool_context, params) do
      case ADK.ToolContext.get_credential(tool_context, "github_token", raw_cred) do
        {:ok, cred} ->
          make_github_api_call(cred.access_token, params)

        :needs_auth ->
          auth_config = ADK.Auth.Config.new(
            credential_type: :oauth2,
            provider: "github",
            scopes: ["repo"]
          )
          {:ok, tc2} = ADK.ToolContext.request_credential(tool_context, auth_config)
          {:auth_required, tc2}

        {:error, reason} ->
          {:error, reason}
      end
    end

## Options

- `:redirect_uri` — used during auth code exchange
- `:refresh_buffer` — seconds before expiry for proactive refresh (default: 300)
- `:http_opts` — extra options for token requests

# `get_state`

```elixir
@spec get_state(t(), term(), term()) :: term()
```

Read a value from session state.

# `has_credential?`

```elixir
@spec has_credential?(t(), String.t()) :: boolean()
```

Check if a credential exists in the credential service.

# `list_artifacts`

```elixir
@spec list_artifacts(t()) :: {:ok, [String.t()]} | {:error, term()}
```

List artifact filenames for the current session.

# `load_artifact`

```elixir
@spec load_artifact(t(), String.t(), keyword()) ::
  {:ok, map()} | :not_found | {:error, term()}
```

Load an artifact by filename.

Options:
- `:version` — specific version to load (default: latest)

# `load_credential`

```elixir
@spec load_credential(t(), String.t()) ::
  {:ok, ADK.Auth.Credential.t()} | :not_found | {:error, term()}
```

Load a credential from the credential service (raw — no exchange/refresh).

Returns `{:ok, credential}` or `:not_found` or `{:error, reason}`.

For a fully managed credential (auto-exchange + auto-refresh), see `get_credential/3`.

# `new`

```elixir
@spec new(ADK.Context.t(), String.t(), map() | module()) :: t()
```

Create a tool context from an invocation context.

# `put_state`

```elixir
@spec put_state(t(), term(), term()) :: {:ok, t()} | {:error, :no_session}
```

Write a value to session state and track the delta.

# `request_credential`

```elixir
@spec request_credential(t(), ADK.Auth.Config.t()) :: {:ok, t()} | {:error, term()}
```

Request a credential for the current tool call.

This records the auth config in event actions so the runner can surface
an auth challenge to the user/client. Only works in tool context
(requires `function_call_id`).

# `save_artifact`

```elixir
@spec save_artifact(t(), String.t(), map(), keyword()) ::
  {:ok, non_neg_integer(), t()} | {:error, term()}
```

Save an artifact and track the version in event actions.

Returns `{:ok, version, updated_context}` on success.
Returns `{:error, :no_artifact_service}` if no artifact service is configured.

# `save_credential`

```elixir
@spec save_credential(t(), String.t(), ADK.Auth.Credential.t()) ::
  :ok | {:error, term()}
```

Save a credential to the credential service.

# `transfer_to_agent`

```elixir
@spec transfer_to_agent(t(), String.t()) :: ADK.Event.t()
```

Request transfer to another agent by name.

Returns an event with a transfer action that the runner will handle.

---

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