Genai Agent

Demonstrates how to wrap a genai multi-provider LLM client behind the A2A protocol. Incoming A2A messages are forwarded to the LLM, and the response is returned as an A2A artifact.

Source: examples/genai-agent/

Supported providers

ProviderModel exampleEnv var
OpenAIgpt-4o, gpt-4o-miniOPENAI_API_KEY
Anthropicclaude-sonnet-4-20250514ANTHROPIC_API_KEY
Google Geminigemini-1.5-flashGEMINI_API_KEY
Ollamallama3(local, no key)
Groqllama3-70b-8192GROQ_API_KEY
Coherecommand-r-plusCOHERE_API_KEY

Running

# GENAI_MODEL defaults to qwen3.5:0.8b, which runs locally (see below), so
# name a hosted model to use a hosted key:
export OPENAI_API_KEY=sk-...
GENAI_MODEL=gpt-4o-mini cargo run -p genai-a2a-agent

# Use a different model:
GENAI_MODEL=claude-sonnet-4-20250514 cargo run -p genai-a2a-agent

Without A2A_BIND_ADDR, cargo run is a self-driving demo, not a server: it starts the agent on all four bindings, drives every A2A method over each, prints LLM leg: EXERCISED or LLM leg: NOT EXERCISED, and exits. In that demo a provider error is answered with a labelled mechanical fallback ([no model reachable — mechanical fallback, not an LLM answer]), so the protocol mechanics stay visible with no model at all. Set A2A_BIND_ADDR to serve instead — JSON-RPC on that address, where a provider error fails the task unless A2A_ALLOW_FALLBACK=1 turns the fallback back on.

How it works

A2A Client ──→ A2A Server (JSON-RPC)
                    │
                    ▼
              GenaiAgentExecutor
                    │
              1. Extract user text (no text part → TASK_STATE_FAILED)
              2. Transition to Working
              3. Call genai::Client for LLM completion
              4. Success → artifact + Completed
                 LLM error → TASK_STATE_FAILED when serving
                             (labelled fallback artifact in the demo)

Fully local, no API key

Model names that don't match a hosted provider route to the Ollama adapter on :11434 — which is also what llama.cpp's llama-server speaks:

GENAI_MODEL=qwen3.5:0.8b cargo run -p genai-a2a-agent

Served with A2A_BIND_ADDR, the agent publishes a discovery card, supports push-config CRUD, and passes the in-repo TCK: 21/21 graded checks, 1 not applicable, on the JSON-RPC binding. tck.yml's tck-example-agents job re-runs that grade on every push and pull request, with no model configured — the TCK grades protocol conformance, and none of it reaches the executor's brain.

Key integration point

The GenaiAgentExecutor implements AgentExecutor — the single trait that bridges any LLM framework with A2A. The integration is ~60 lines of code: extract text from the A2A message, call the genai client, and emit the result as an artifact.

This pattern is the same for any LLM integration — see also the Rig Agent for an alternative framework.