elixir · agents · sandboxes

Define and run AI agents. In Elixir.

Condukt is an Elixir framework for defining and running AI agents. Agents are supervised OTP processes, every session is sandboxed with governed network egress, and tools, secrets, and sub-agents compose inside the same runtime.

# Add to mix.exs
{:condukt, "~> 1.5"}
# Fetch dependencies
mix deps.get

section 01

What Condukt gives you

OTP-native

Agents are supervised GenServers. They live in your supervision tree and recover from crashes the way the rest of your system does.

Sandboxed sessions

Every session runs through one sandbox facade: the host, an in-memory Rust filesystem, or a dedicated Kubernetes pod cloned from a git workspace.

Governed egress

Per-session network policy with allow and deny host globs, plus an LLM-backed decide rule. Egress is audited and secrets are redacted.

Pluggable runtimes

Use the native ReqLLM tool loop, or wrap the Codex and Claude CLIs as drop-in agent runtimes without leaving Condukt.

Typed operations

Expose compile-time entrypoints with JSON Schema validated input and output so callers can run constrained agent tasks without parsing free-form text.

MCP client

Connect external Model Context Protocol servers over stdio, HTTP SSE, or streamable HTTP. Their tools appear to agents as server.tool.

Sub-agents & HTTP

Delegate to role-based child agents with typed inputs and outputs, and expose any agent or operation as a JSON endpoint via Condukt.Plug.

Multi-provider streaming

18+ LLM providers through ReqLLM, with real-time event streams for text, thinking, and tool calls. Built for Phoenix LiveView.

section 02

Sandboxed and governed by default

Declare a sandbox on the agent and every session is isolated. A Kubernetes sandbox runs each session in its own pod. A network policy decides what that pod may reach, with an agent as the final arbiter on ambiguous hosts.

defmodule MyApp.CodingAgent do
use Condukt
@impl true
def tools, do: Condukt.Tools.coding_tools()
@impl true
def sandbox do
{Condukt.Sandbox.Kubernetes,
namespace: "agents",
image: "ghcr.io/myorg/agent:1.4",
workspace_source: [git: "https://github.com/myorg/repo.git", ref: "main"],
network_policy: %Condukt.Sandbox.NetworkPolicy{
rules: [
deny: ["*.internal.example.com"],
allow: ["api.github.com", "*.hex.pm"],
decide: {Condukt.Sandbox.NetworkPolicy.AgentDecider, agent: MyApp.NetGuard}
],
default: :deny
}}
end
end

# Local and in-memory Virtual sandboxes share the same facade. Swap Condukt.Sandbox.Kubernetes for Condukt.Sandbox.Virtual to run tools against an in-memory Rust filesystem instead. Read the sandbox guide →

section 03

Run agents your way

Use the same agent definition for single-call work or persistent sessions. Both paths share the same tools, sandboxes, secrets, and network policy.

Choose the lifecycle

Use one-shot runs for scripts, jobs, request handlers, and CI. Start a supervised session when you need streaming, persistence, or repeated prompts against the same agent.

  1. Run it once

    Pass the agent module to Condukt.run/3 and Condukt creates a transient session for that call.

  2. Keep it alive

    Start the agent with start_link/1, then send prompts to the running session.

# One-shot
{:ok, response} =
Condukt.run(MyApp.CodingAgent, "Refactor this module.",
api_key: System.fetch_env!("ANTHROPIC_API_KEY")
)
# Persistent session
{:ok, agent} =
MyApp.CodingAgent.start_link(
api_key: System.fetch_env!("ANTHROPIC_API_KEY")
)
{:ok, response} = Condukt.run(agent, "Refactor this module.")

# Same agent definition, two lifecycles. Read the one-shot runs guide →