Class: Esp::Agent
- Inherits:
-
Object
- Object
- Esp::Agent
- Defined in:
- lib/esp/agent.rb
Overview
A hand-rolled tool-use loop. The agent authors mods by calling the same curated tool surface MCP exposes (Esp::McpServer::TOOLS), each tool dispatched to Esp::Operations.public_send(op, …) — so the in-house agent and external MCP clients share one tool definition.
The LLM is reached through an injected provider (see Esp::Providers), so the loop is provider-agnostic and fully testable with a stub and no live key. When none is given, the default provider is built from the registry (Esp::Providers.default_id). See .claude/roadmap/19-agent-workspace.md.
Transcript shape (neutral, owned by Agent; providers translate it to their native wire format):
{ role: :user, text: String }
{ role: :assistant, text: String, tool_calls: [{id:, name:, input:}],
raw: <provider-native message, opaque to Agent> }
{ role: :tool, results: [{id:, content: String, is_error: bool}] }
Defined Under Namespace
Classes: Result
Constant Summary collapse
- MAX_TURNS =
20- SYSTEM =
<<~PROMPT.freeze You are the authoring agent inside ESPresso, the GUI for the `esp` Morrowind modding toolchain. You build and edit mods by calling the provided tools, which operate on the user's mod project as diffable source. Read current state (records_read, refs_find) before writing. Make the smallest change that satisfies the request, then build and lint to confirm. Keep explanations brief — the human reviews the diff. PROMPT
Instance Method Summary collapse
-
#initialize(provider: nil, system: SYSTEM, max_turns: MAX_TURNS) ⇒ Agent
constructor
A new instance of Agent.
-
#run(prompt, &on_event) ⇒ Object
Run the loop to completion for one user prompt.
Constructor Details
#initialize(provider: nil, system: SYSTEM, max_turns: MAX_TURNS) ⇒ Agent
Returns a new instance of Agent.
34 35 36 37 38 |
# File 'lib/esp/agent.rb', line 34 def initialize(provider: nil, system: SYSTEM, max_turns: MAX_TURNS) @provider = provider || Esp::Providers.build(Esp::Providers.default_id) @system = system @max_turns = max_turns end |
Instance Method Details
#run(prompt, &on_event) ⇒ Object
Run the loop to completion for one user prompt. Optionally yields events as they happen ([:text, str] / [:tool_use, name, input] /
- :tool_result, name, payload
-
/ [:tool_error, name, error]) for a
streaming UI to render.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/esp/agent.rb', line 44 def run(prompt, &on_event) = [{ role: :user, text: prompt }] @max_turns.times do completion = @provider.complete(system: @system, tools: tool_definitions, messages: ) tool_calls = Array(completion.tool_calls) << { role: :assistant, text: completion.text, tool_calls: tool_calls, raw: completion.raw } on_event&.call([:text, completion.text]) unless completion.text.to_s.empty? break if tool_calls.empty? << { role: :tool, results: tool_calls.map { |tc| run_tool(tc, &on_event) } } end Result.new(text: final_text(), messages: ) end |