rony-llm-agent/pkg/agent
Victor Vargas 744bb00f88 feat(agent): add SubAgent runtime for nested, specialized agent loops
Implements docs/phase2.md §5 (Sub-agents), pulled forward from the
harness's item 2 work: SubAgent/SubAgentRegistry let a caller run a
nested agent.Loop with its own persona/tools/iteration cap and get its
final response back. Run doesn't set Approver/Sandbox, so a single Ask
approval on the caller's own delegating tool covers the whole nested
run (Ask-permission tools execute unprompted when Config.Approver is
nil). rony-harness consumes this for its delegate tool (builder/planner).
2026-07-09 12:08:32 -07:00
..
integration_test.go Fix tool call tracking and streaming assembly for all providers 2026-07-08 16:11:57 -07:00
loop.go feat(agent): wire AGENTS.md discovery into the agent loop's system prompt 2026-07-08 23:27:17 -07:00
loop_test.go feat(agent): wire AGENTS.md discovery into the agent loop's system prompt 2026-07-08 23:27:17 -07:00
README.es.md feat: add history messages, reasoning content, and adaptive language support 2026-07-05 16:17:37 -07:00
README.md feat: add history messages, reasoning content, and adaptive language support 2026-07-05 16:17:37 -07:00
subagent.go feat(agent): add SubAgent runtime for nested, specialized agent loops 2026-07-09 12:08:32 -07:00
subagent_test.go feat(agent): add SubAgent runtime for nested, specialized agent loops 2026-07-09 12:08:32 -07:00

pkg/agent

The main loop that runs an LLM agent with guardrails.

Responsibility

Coordinate the iterative cycle between the LLM and tool execution:

while iteration < MaxIterations:
    response = llm.Generate(messages, tools)
    if no tool calls: return response
    for tool_call in response.ToolCalls:
        if needs_approval: ask_user()
        result = execute(tool_call)
        append tool result to messages

Public API

type Loop interface {
    Run(ctx context.Context, input string, history ...llm.Message) (Response, error)
    RunStream(ctx context.Context, input string, history ...llm.Message) iter.Seq2[Chunk, error]
}

type Config struct {
    LLM          llm.LLMClient
    Persona      persona.Persona
    Tools        tools.Registry
    Sandbox      Sandbox
    MaxIters     int
    Approver     Approver        // nil = auto-approve all
    OnIteration  func(Iteration) // observability hook
}

type Response struct {
    Content     string
    ToolCalls   []tools.Call
    Iterations  int
    Duration    time.Duration
    TokenUsage  llm.TokenUsage
}

Guarantees

  • Termination: Always terminates (max iterations, error, or final response)
  • Idempotency: Re-running with the same input produces the same output (given the same LLM)
  • Observability: Each iteration emits an OpenTelemetry span
  • Approval: Destructive tools (Ask permission) require confirmation

See also