# `Mojentic.Agents.AsyncLLMAgent`
[🔗](https://github.com/svetzal/mojentic-ex/blob/v1.2.0/lib/mojentic/agents/async_llm_agent.ex#L1)

Asynchronous agent that uses an LLM to generate responses.

This module provides a reusable pattern for creating async agents that
interact with language models. It wraps the synchronous `Mojentic.LLM.Broker`
operations in async tasks to avoid blocking the dispatcher.

## Features

- **Behaviour** - System prompt defining agent personality
- **Response Model** - JSON schema for structured output
- **Tools** - List of tools available to the LLM
- **Async Generation** - Non-blocking LLM calls

## Usage

You can use this module in two ways:

1. **Direct instantiation** with `new/1` (returns a map with behaviour)
2. **Implementation helper** with `use Mojentic.Agents.AsyncLLMAgent` in your module

## Examples

    # Option 1: Direct instantiation
    defmodule MyAgent do
      @behaviour Mojentic.Agents.BaseAsyncAgent

      def init(broker) do
        AsyncLLMAgent.new(
          broker: broker,
          behaviour: "You are a helpful fact-checker.",
          response_model: %{
            "type" => "object",
            "properties" => %{
              "facts" => %{"type" => "array", "items" => %{"type" => "string"}}
            }
          }
        )
      end

      @impl true
      def receive_event_async(event) do
        agent = init(broker)
        prompt = "Check facts about: #{event.question}"
        {:ok, response} = AsyncLLMAgent.generate_response(agent, prompt)
        {:ok, [create_fact_event(response, event.correlation_id)]}
      end
    end

    # Option 2: Using the module directly
    defmodule FactChecker do
      use Mojentic.Agents.AsyncLLMAgent

      def init(broker) do
        new(
          broker: broker,
          behaviour: "You are a fact-checker.",
          response_model: fact_schema()
        )
      end
    end

# `t`

```elixir
@type t() :: %Mojentic.Agents.AsyncLLMAgent{
  behaviour: String.t(),
  broker: Mojentic.LLM.Broker.t(),
  response_model: map() | nil,
  tools: [module()] | nil
}
```

# `__using__`
*macro* 

Enables using this module in your own agent modules.

When you `use Mojentic.Agents.AsyncLLMAgent`, you get helper functions
for working with async LLM agents in your own implementations.

## Example

    defmodule MyFactChecker do
      use Mojentic.Agents.AsyncLLMAgent

      @behaviour Mojentic.Agents.BaseAsyncAgent

      def init(broker) do
        new(
          broker: broker,
          behaviour: "You are a fact-checker.",
          response_model: my_schema()
        )
      end

      @impl true
      def receive_event_async(event) do
        agent = init(get_broker())
        {:ok, response} = generate_response(agent, event.question)
        {:ok, [create_event(response, event)]}
      end
    end

# `create_initial_messages`

Creates initial messages from the agent's behaviour.

Returns a list containing the system message with the agent's behaviour.

## Examples

    iex> agent = AsyncLLMAgent.new(broker: broker, behaviour: "You are helpful.")
    iex> AsyncLLMAgent.create_initial_messages(agent)
    [%Message{role: :system, content: "You are helpful."}]

# `generate_response`

Generates a response from the LLM asynchronously.

This function wraps the synchronous broker call in a Task to avoid blocking.
It handles both structured output (via response_model) and free-form generation.

## Parameters

- `agent` - The AsyncLLMAgent configuration
- `content` - The user prompt string

## Returns

- `{:ok, response}` - The LLM response (string or parsed object)
- `{:error, reason}` - Generation failed

## Examples

    {:ok, response} = AsyncLLMAgent.generate_response(agent, "What is 2+2?")

    # With structured output
    {:ok, %{"answer" => "4", "confidence" => 1.0}} =
      AsyncLLMAgent.generate_response(agent, "What is 2+2?")

# `new`

Creates a new AsyncLLMAgent configuration.

## Parameters

- `opts` - Keyword list with:
  - `:broker` - LLM broker instance (required)
  - `:behaviour` - System prompt defining agent behavior (required)
  - `:response_model` - JSON schema for structured output (optional)
  - `:tools` - List of tool modules (optional)

## Examples

    broker = Broker.new("qwen3:32b", Ollama)

    agent = AsyncLLMAgent.new(
      broker: broker,
      behaviour: "You are a helpful assistant.",
      response_model: %{
        "type" => "object",
        "properties" => %{
          "answer" => %{"type" => "string"},
          "confidence" => %{"type" => "number"}
        }
      }
    )

---

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