Jidoka: Web Tools
Web access is a constrained capability. Jidoka exposes search and read-only page tools without exposing arbitrary browser control to the model.
Setup
Mix.install(
[
{:jidoka, git: "https://github.com/mikehostetler/jidoka.git", ref: "924a486f3c1b7e7a943cb3d5ceee0de65f158467"},
{:kino, "~> 0.19.0"}
],
config: [
jidoka: [
model_aliases: %{fast: "anthropic:claude-haiku-4-5"}
]
]
)
Jidoka.Kino.setup()
Define Web Agents
defmodule LivebookDemo.Web.SearchAgent do
use Jidoka.Agent
agent do
id :livebook_web_search_agent
end
defaults do
model :fast
instructions "You can search the public web."
end
capabilities do
web :search
end
end
defmodule LivebookDemo.Web.ReadOnlyAgent do
use Jidoka.Agent
agent do
id :livebook_web_read_only_agent
end
defaults do
model :fast
instructions "You can search and read public web pages."
end
capabilities do
web :read_only
end
end
Compare the exposed tools.
[
%{
agent: "search",
web_tool_names: LivebookDemo.Web.SearchAgent.web_tool_names(),
tool_names: LivebookDemo.Web.SearchAgent.tool_names()
},
%{
agent: "read_only",
web_tool_names: LivebookDemo.Web.ReadOnlyAgent.web_tool_names(),
tool_names: LivebookDemo.Web.ReadOnlyAgent.tool_names()
}
]
Safety Boundary
Read-only page tools reject localhost, loopback, and private network URLs before browser work starts.
{:error, read_error} = Jidoka.Web.Tools.ReadPage.run(%{url: "http://localhost:4000"}, %{})
{:error, snapshot_error} = Jidoka.Web.Tools.SnapshotUrl.run(%{url: "http://192.168.1.10"}, %{})
Jidoka.Kino.table("Web safety checks", [
%{tool: "read_page", message: Jidoka.format_error(read_error)},
%{tool: "snapshot_url", message: Jidoka.format_error(snapshot_error)}
])
Inspect the read-only agent like any other tool-bearing agent.
{:ok, definition} = Jidoka.inspect_agent(LivebookDemo.Web.ReadOnlyAgent)
Map.take(definition, [:id, :tool_names, :web])
Optional Provider Turn
{:ok, pid} =
Jidoka.Kino.start_or_reuse("livebook-web-read-only-agent", fn ->
LivebookDemo.Web.ReadOnlyAgent.start_link(id: "livebook-web-read-only-agent")
end)
Jidoka.Kino.chat("Web-capable chat", fn ->
LivebookDemo.Web.ReadOnlyAgent.chat(pid, "What web tools are available to you?")
end)