0.9.2
raw

Embedded LLM Module (agent_smith/llm)

Overview

This document describes the current implemented LLM contract used by Agent Smith.

1. Scope and boundary

agent_smith/llm owns protocol mechanics only:

It does not own turn orchestration, role policy, dispatch, UI, or persistence.


2. Public surface

Top-level entry: agent_smith/llm.lua

Client constructor/export (llm/client.lua) also exposes helper methods:


3. Request contract

Required core fields

  • model

  • messages (array)

Optional fields currently passed through

  • tools

  • tool_choice

  • stream

  • temperature

  • max_new_tokens

  • cancel (runtime cancellation token/handle)

Message validation and normalization

sanitize_messages enforces sequence correctness:

  • assistant tool calls must have IDs

  • tool results must reference known pending tool call IDs

  • no duplicate or dangling tool call IDs

  • tool result content is stringified when needed

Invalid ordering/shape returns schema/protocol errors before transport.


4. Response contract

Non-streaming chat returns normalized payload:

Errors are normalized to agent_error with stable kind/code when possible.

No implicit retry loop is performed inside the raw client.

Transport and empty-response retries are handled by the turn layer (core/turn.lua).


5. Streaming contract

chat_stream(request, handlers) supports handlers:

Accepted SSE message payload forms in llm/client.lua:

llm/stream.lua assembler:

SSE polling checks cancellation between sse:update() iterations.

update() == false while still connected is treated as transient up to a bounded threshold; if it persists, streaming fails with explicit stream_stalled error instead of silently finalizing.

on_done is called only on successful stream completion (explicit done/disconnect path). Protocol/transport failures surface as errors and do not synthesize success.


6. Tool payload contracts

agent_smith.llm.tool exports:

Tool schema input expectations

build_tool_schema expects:

  • tool_spec.name (string)

  • tool_spec.input_schema (table)

It emits Chat Completions wire shape:

{
  "type": "function",
  "function": {
    "name": "...",
    "description": "...",
    "parameters": { "...": "..." }
  }
}

Naming mapping

  • LLM call field: id

  • runtime field: call_id

  • tool message wire field: tool_call_id


7. Model helpers

Catalog fetch (llm/model/catalog.lua)

  • Fetches GET /models from Chat Completions-compatible API base.

  • Normalizes entries into descriptors (id, name, context/output token hints, raw).

Discovery (llm/model/discovery.lua)

Implemented strategies:

  • first_available

  • prefer_prefix

  • prefer_capability_tag

  • fallback_chain

Each returns { model_id, reason } on success.


8. Limitations

  1. Protocol support is Chat Completions-compatible only.

  2. No provider abstraction or multi-provider negotiation.

  3. No automatic retries inside the raw LLM client.

  4. Non-stream cancellation is checked before/after request boundaries.

  5. Stream cancellation depends on SSE poll/update cadence and transport timeouts.

  6. Discovery helpers are available but not automatically used by runtime model selection.