rony-llm-agent/pkg/agent
Victor Vargas 3ac9d89b98 Fix tool call tracking and streaming assembly for all providers
- agent/loop.go: Record assistant message with ToolCalls before tool results,
  and set ToolCallID on tool-result messages so follow-up requests have complete
  context (prevents models from losing track of already-attempted tools).

- llm/providers/llamacpp/client.go: Buffer fragmented tool call deltas during
  streaming, assemble them into complete calls when finish_reason arrives.
  Add ToolCalls, ToolCallID, Name fields to request building.

- llm/providers/openai/client.go: Send ToolCalls, ToolCallID, Name when
  building chat requests so messages are wire-format correct.

- llm/types.go: Add ToolCalls field to Message struct for serialization
  back into conversation history.

- agent/integration_test.go: Move integration test skip from TestMain to a
  per-test skipUnlessIntegration() so it doesn't hide other package tests.

- sandbox & tools: Add edge-case tests (relative traversal, array paths,
  non-path strings, zero-value guards, sentinel errors).
2026-07-08 16:11:57 -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 Fix tool call tracking and streaming assembly for all providers 2026-07-08 16:11:57 -07:00
loop_test.go Fix tool call tracking and streaming assembly for all providers 2026-07-08 16:11:57 -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

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