Nous.Tool.Behaviour behaviour (nous v0.13.3)
View SourceBehaviour for tool implementations.
Allows tools to be defined as modules for better testability and organization. Module-based tools can inject dependencies via the context, making them easy to test with mocks.
Example
defmodule MyApp.Tools.Search do
@behaviour Nous.Tool.Behaviour
@impl true
def metadata do
%{
name: "search",
description: "Search the web for information",
parameters: %{
"type" => "object",
"properties" => %{
"query" => %{
"type" => "string",
"description" => "The search query"
}
},
"required" => ["query"]
}
}
end
@impl true
def execute(ctx, %{"query" => query}) do
# Inject http_client via deps for testing
http_client = ctx.deps[:http_client] || Nous.HTTP
api_key = ctx.deps[:search_api_key]
case http_client.get("https://api.search.com", query: query, key: api_key) do
{:ok, results} -> {:ok, format_results(results)}
{:error, _} = err -> err
end
end
defp format_results(results), do: Enum.map(results, & &1["title"])
endTesting
defmodule MyApp.Tools.SearchTest do
use ExUnit.Case
test "search returns formatted results" do
mock_http = %{
get: fn _url, _opts ->
{:ok, [%{"title" => "Result 1"}, %{"title" => "Result 2"}]}
end
}
ctx = Nous.RunContext.new(%{http_client: mock_http, search_api_key: "test"})
assert {:ok, ["Result 1", "Result 2"]} =
MyApp.Tools.Search.execute(ctx, %{"query" => "elixir"})
end
endUsage with Agent
agent = Nous.Agent.new("openai:gpt-4",
tools: [Nous.Tool.from_module(MyApp.Tools.Search)]
)
Summary
Callbacks
Execute the tool with context and arguments.
Return tool metadata (name, description, parameters).
Return the tool's schema definition for introspection.
Functions
Get metadata from a module, using defaults if metadata/0 is not implemented.
Check if a module implements the Tool.Behaviour.
Convert a module name to a tool name.
Callbacks
@callback execute(ctx :: Nous.RunContext.t(), args :: map()) :: {:ok, any()} | {:ok, any(), Nous.Tool.ContextUpdate.t()} | {:error, term()}
Execute the tool with context and arguments.
The context provides access to dependencies and execution metadata. Arguments are a map of the parameters passed by the LLM.
Return Values
{:ok, result}- Success with the result to return to the LLM{:ok, result, context_update}- Success with context updates (seeNous.Tool.ContextUpdate){:error, reason}- Failure with error reason
@callback metadata() :: map()
Return tool metadata (name, description, parameters).
This callback is optional. If not implemented, the tool name will be derived from the module name.
Return Value
%{
name: "tool_name",
description: "What the tool does",
parameters: %{
"type" => "object",
"properties" => %{...},
"required" => [...]
}
}
@callback schema() :: map()
Return the tool's schema definition for introspection.
This callback is optional. When using Nous.Tool.Schema, it is
generated automatically as __tool_schema__/0.
Return Value
%{
name: "tool_name",
description: "...",
category: :read,
tags: [:file],
params: [
%{name: :path, type: :string, required: true, doc: "..."},
...
]
}