brute
A framework-agnostic coding agent for Ruby. Rack-style middleware pipelines for agent turns, a full set of coding tools, and session persistence — bring your own LLM library.
Brute treats an agent turn the way Rack treats an HTTP request: an env hash
flowing through a middleware stack toward a terminal app. The middleware handles
the agentic machinery — the tool loop, session persistence, the system prompt,
iteration guards. The terminal app is a proc you write with whatever LLM
library you prefer (ruby_llm,
llm.rb, the official
openai or
anthropic gems, or raw
HTTP). Brute depends on none of them.
Usage
See the project documentation:
- Getting Started — install brute and build your first agent.
-
The Agent Pipeline —
Brute.agent,.use,.run,.start. -
Messages — the
Brute::Messageformat. - Message Transports — translate between Brute and any LLM library.
- Tools — four ways to define a tool; the built-in coding toolset.
- Middleware — the built-in turn middleware catalog.
Quick start
require "brute"
require "ruby_llm"
agent = Brute.agent
.use(Brute::Middleware::SessionLog, path: "tmp/session.jsonl")
.use(Brute::Middleware::SystemPrompt)
.use(Brute::Middleware::Loop::ToolResult)
.use(Brute::Middleware::MaxIterations)
.use(Brute::Middleware::ToolPipeline, tools: Brute::Tools::ALL)
.run do |env|
response = provider.complete(
Brute::MessageTransport::RubyLLM.dump_all(env[:messages]),
tools: rubyllm_tools(env[:tools]), model: model,
)
Brute::MessageTransport::RubyLLM.wrap_each(response) { |m| env[:messages] << m }
end
agent.start("What files are in the current directory?")Docs
The documentation site is a Just the Docs Jekyll
project under docs/. Serve it locally:
docs/bin/serve.sh # http://localhost:4000/brute/See Also
- Examples directory — the same agent on four LLM libraries, plus sub-agents, sessions, and HTTP serving.
License
MIT