README.md

# ExAI

ExAI is a lightweight, graph-first runtime for building agent systems on the
BEAM in Elixir.

## Development

### Start the app

```bash
iex -S mix
```

### Run tests

```bash
mix test
```

### Run Dialyzer

```bash
mix dialyzer
```

### Feature flags

Feature flags are configured under `config/config.exs`:

```elixir
config :ex_ai,
  web_enabled: false,
  remote_execution_enabled: false,
  extism_enabled: false,
  delegate_cli_enabled: false
```

Use `ExAI.feature_enabled?/1` to query them at runtime.

### Mermaid graph export

```elixir
graph =
  ExAI.Graph.new(id: :sample)
  |> ExAI.Graph.step(:fetch, &{:ok, &1})
  |> ExAI.Graph.edge(:start, :fetch)
  |> ExAI.Graph.edge(:fetch, :end)

ExAI.Graph.mermaid(graph, direction: :TD)
```

### Graph runtime examples

```bash
mix run examples/graph/simple_flow.exs
mix run examples/graph/fanout_join.exs
mix run examples/graph/cancelled_run.exs
```

### Agent quickstart

```elixir
agent =
  ExAI.Agent.new(
    name: :support,
    instructions: "Answer using available context",
    model: fn request -> %{content: "Echo: #{request.input}"} end
  )

{:ok, context} = ExAI.Agent.run(agent, "hello")
context.result.output
```

### Direct provider adapters

```elixir
transport = fn _request ->
  {:ok, %{status: 200, body: %{"choices" => [%{"message" => %{"content" => "ok"}}]}}}
end

agent =
  ExAI.Agent.new(
    name: :provider_agent,
    model:
      {:provider, :openai_compatible,
       api_key: {:env, "OPENAI_API_KEY"}, transport: transport}
  )
```

Supported direct providers:

- `:openai_compatible`
- `:anthropic`

### Delegate CLI adapters

```elixir
agent =
  ExAI.Agent.new(
    name: :delegate_agent,
    model: {:delegate, :codex_cli, command: "codex", args: ["exec"]}
  )
```

Supported delegate adapters:

- `:codex_cli`
- `:claude_code`

Missing executables, timeouts, and parse failures are normalized into typed
`ExAI.Error` values.

### Agent runtime examples

```bash
mix run examples/agent/simple_agent.exs
mix run examples/agent/tool_agent.exs
mix run examples/agent/validated_json_agent.exs
```

### End-to-end examples

```bash
mix run examples/e2e/provider_backed_agent.exs
mix run examples/e2e/delegate_cli_backed_agent.exs
mix run examples/e2e/remote_worker_graph.exs
mix run examples/e2e/just_bash_graph.exs
```

### Assistant-facing CLI docs

- Codex CLI usage: `docs/codex_cli_usage.md`
- Codex examples: `examples/codex_cli/`
- Claude Code usage: `docs/claude_code_usage.md`
- Claude examples: `examples/claude_code/`
- Model adapter usage (provider vs delegate): `docs/model_adapter_usage.md`
- JSON/JSONL contract: `docs/cli_contract.md`
- Release checklist and operational notes: `docs/release_checklist.md`

### Local web shell (minimal)

```elixir
{:ok, _pid} = ExAI.Web.Shell.start(port: 4007)
```

Then open:

- `http://127.0.0.1:4007/runs`
- `http://127.0.0.1:4007/api/runs`
- `http://127.0.0.1:4007/runs/<run_id>/stream` (SSE view)