defmodule CodingAgent do
@moduledoc """
A small library for building coding-agent harnesses on top of OpenRouter
(via `req_llm`), with each agent conversation running as its own
`GenServer` session and support for Claude-Code-style skills (directories
with a `SKILL.md` that the agent can discover and invoke).
File tools (`read`/`write`/`edit`) operate on an in-memory `path =>
content` map rather than the real filesystem; `send_message/3` hands that
map back to the caller so they can persist it (or not) however they like.
## Quick start
CodingAgent.OpenRouter.configure!() # reads OPENROUTER_API_KEY
{:ok, pid} = CodingAgent.start_session(
model: CodingAgent.OpenRouter.model("anthropic/claude-sonnet-4.5"),
skills_dirs: ["skills"],
files: %{"lib/foo.ex" => File.read!("lib/foo.ex")}
)
{:ok, reply, files} = CodingAgent.send_message(pid, "Fix the failing test in lib/foo.ex")
# caller decides what to do with the result, e.g. write it back out:
Enum.each(files, fn {path, content} -> File.write!(path, content) end)
See `CodingAgent.Session` for the full set of options.
"""
alias CodingAgent.Session
@doc "Starts an unsupervised agent session. See `CodingAgent.Session.start_link/1` for options."
defdelegate start_session(opts \\ []), to: Session, as: :start_link
@doc "Sends a message to a session and runs the agent loop to completion. Returns `{:ok, reply, files}`."
defdelegate send_message(session, text, timeout \\ 120_000), to: Session
@doc """
Like `send_message/3`, but calls `on_chunk` with each text chunk as the
model produces it. Returns the same `{:ok, reply, files}` shape once the
full turn (including any tool round-trips) has finished.
"""
defdelegate stream_message(session, text, on_chunk, timeout \\ 120_000), to: Session
@doc "Returns the full conversation context for a session."
defdelegate context(session), to: Session
@doc "Returns a session's current in-memory workspace (`path => content`)."
defdelegate files(session), to: Session
end