Code.require_file("../../support.exs", __DIR__) defmodule BeamWeaver.Examples.DeepAgents.Support do @moduledoc false alias BeamWeaver.Agent alias BeamWeaver.Agent.Middleware.ToolSelection alias BeamWeaver.ExecutionPolicy alias BeamWeaver.Examples.Support @node_timeout 60_000 @concise_suffix """ Complete the user's request with one concise sentence. Do not call tools unless absolutely necessary. """ def create(opts) do opts = opts |> add_concise_prompt() |> maybe_disable_visible_tools() |> Keyword.put_new(:model_opts, default_model_opts()) case Agent.build(opts) do {:ok, agent} -> {:ok, extend_timeout(agent)} other -> other end end def model, do: Support.model() defp default_model_opts do base = [max_tokens: 256, max_output_tokens: 256, timeout: @node_timeout] if String.starts_with?(Support.model_id(), "zai:") do base else Keyword.put(base, :tool_choice, "none") end end defp add_concise_prompt(opts) do Keyword.update(opts, :system_prompt, @concise_suffix, fn nil -> @concise_suffix prompt -> to_string(prompt) <> "\n\n" <> @concise_suffix end) end defp maybe_disable_visible_tools(opts) do if String.starts_with?(Support.model_id(), "zai:") do Keyword.update(opts, :middleware, [ToolSelection.new(allow: [])], fn middleware -> List.wrap(middleware) ++ [ToolSelection.new(allow: [])] end) else opts end end defp extend_timeout(agent), do: update_in(agent.compiled, &extend_compiled_timeout/1) defp extend_compiled_timeout(compiled) do graph = extend_graph_timeout(compiled.graph) %{compiled | graph: graph, plan: %{compiled.plan | graph: graph}} end defp extend_graph_timeout(graph) do nodes = Map.new(graph.nodes, fn {name, spec} -> {name, %{spec | timeout: @node_timeout, execution_policy: ExecutionPolicy.new!(timeout: @node_timeout)}} end) %{graph | nodes: nodes} end end