# `LlmToolkit.SessionTools`
[🔗](https://github.com/fosferon/llm_toolkit/blob/v0.1.0/{path}#L{line})

Integration layer: filters available tools by session declaration and
builds a context-bound resolver closure.

Called by host session managers before each turn to compose the
`{tools, resolve_tool}` tuple that the conversational engine passes
through to the LLM adapter.

## Design Decision: Closure over Process Dictionary

Context is threaded via a closure that captures `session_context` at
call time. This is pure, thread-safe across concurrent turns, and
unit-testable. Process dictionary was considered but rejected — it's
a leak risk and couples the resolver to the calling process identity.

# `prepare`

```elixir
@spec prepare(module(), [String.t()] | nil, map()) ::
  {[LlmToolkit.Tool.t()],
   (LlmToolkit.Tool.Call.t() -&gt; {:ok, String.t()} | {:error, String.t()}) | nil}
```

Prepare tools and resolver for a session turn.

## Parameters

  * `resolver_mod` — module implementing `LlmToolkit.ToolResolver` with
    an additional `resolve/2` callback for context-aware dispatch.
    Typically generated via `use LlmToolkit.AgentResolver, tools: […]`.
  * `declared_tool_names` — list of tool name strings from persona YAML
    or workflow spec (e.g., `["capture_lead"]`). Nil or empty list means
    no tools — adapter takes single-shot path.
  * `session_context` — map with session-scoped data. Shape is opaque to
    this module; it is forwarded verbatim to `resolver_mod.resolve/2`.

## Returns

  * `{filtered_tools, resolver_fn}` — non-empty tools and a closure
    that dispatches calls with session context bound
  * `{[], nil}` — when no tools are declared or none match available tools

---

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