{"id":32710361,"url":"https://github.com/protocol-lattice/go-agent","last_synced_at":"2026-03-01T11:09:25.272Z","repository":{"id":318735392,"uuid":"1075241121","full_name":"Protocol-Lattice/go-agent","owner":"Protocol-Lattice","description":"Agent framework in Golang","archived":false,"fork":false,"pushed_at":"2025-10-29T06:23:06.000Z","size":1859,"stargazers_count":55,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-29T08:29:06.395Z","etag":null,"topics":["agents","framework","go","llm","multi-agent","open-source","pgvector","qdrant","rag","utcp"],"latest_commit_sha":null,"homepage":"https://protocol-lattice.github.io/go-agent/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Protocol-Lattice.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-13T08:28:36.000Z","updated_at":"2025-10-29T07:55:55.000Z","dependencies_parsed_at":"2025-10-29T08:29:08.990Z","dependency_job_id":"33ce020c-1d0b-409f-8c35-201222dc281a","html_url":"https://github.com/Protocol-Lattice/go-agent","commit_stats":null,"previous_names":["raezil/go-agent-development-kit","raezil/lattice-agent","protocol-lattice/agent","protocol-lattice/go-agent"],"tags_count":53,"template":false,"template_full_name":null,"purl":"pkg:github/Protocol-Lattice/go-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Protocol-Lattice%2Fgo-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Protocol-Lattice%2Fgo-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Protocol-Lattice%2Fgo-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Protocol-Lattice%2Fgo-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Protocol-Lattice","download_url":"https://codeload.github.com/Protocol-Lattice/go-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Protocol-Lattice%2Fgo-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281818058,"owners_count":26566855,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-30T02:00:06.501Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","framework","go","llm","multi-agent","open-source","pgvector","qdrant","rag","utcp"],"created_at":"2025-11-02T05:01:09.511Z","updated_at":"2026-02-16T22:45:24.825Z","avatar_url":"https://github.com/Protocol-Lattice.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Version](https://img.shields.io/badge/Go-1.25-00ADD8?logo=go\u0026logoColor=white)](https://go.dev/dl/)\n[![CI Status](https://github.com/Protocol-Lattice/go-agent/actions/workflows/go.yml/badge.svg)](https://github.com/Protocol-Lattice/go-agent/actions/workflows/go.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/Protocol-Lattice/go-agent.svg)](https://pkg.go.dev/github.com/Protocol-Lattice/go-agent)\n[![Go Report Card](https://goreportcard.com/badge/github.com/Protocol-Lattice/go-agent)](https://goreportcard.com/report/github.com/Protocol-Lattice/go-agent)\n\n**Lattice** helps you build AI agents in Go with clean abstractions for LLMs, tool calling, retrieval-augmented memory, and multi-agent coordination. Focus on your domain logic while Lattice handles the orchestration plumbing.\n\n## Why Lattice?\n\nBuilding production AI agents requires more than just LLM calls. You need:\n\n- **Pluggable LLM providers** that swap without rewriting logic\n- **Tool calling** that works across different model APIs\n- **Memory systems** that remember context across conversations\n- **Multi-agent coordination** for complex workflows\n- **Testing infrastructure** that doesn't hit external APIs\n\nLattice provides all of this with idiomatic Go interfaces and minimal dependencies.\n\n## Features\n\n- 🧩 **Modular Architecture** – Compose agents from reusable modules with declarative configuration\n- 🤖 **Multi-Agent Support** – Coordinate specialist agents through a shared catalog and delegation system\n- 🔧 **Rich Tooling** – Implement the `Tool` interface once, use everywhere automatically\n- 🧠 **Smart Memory** – RAG-powered memory with importance scoring, MMR retrieval, and automatic pruning\n- 🔌 **Model Agnostic** – Adapters for Gemini, Anthropic, Ollama, or bring your own\n- 📡 **UTCP Ready** – First-class Universal Tool Calling Protocol support\n- ⚡ **High Performance** – Optimized with LRU caching, pre-allocated buffers, and concurrent operations\n\n### ⚡ Performance Optimizations\n\nLattice is built for production speed:\n\n- **10-50x faster MIME normalization** with pre-computed lookup tables and caching\n- **40-60% fewer allocations** in prompt building through buffer pre-allocation\n- **LRU cache infrastructure** for sub-millisecond cached operations (184 ns/op)\n- **Concurrent utilities** for parallel processing with configurable worker pools\n- **Optimized string operations** reduce overhead by 30-50%\n\nSee [PERFORMANCE_SUMMARY.md](./PERFORMANCE_SUMMARY.md) for detailed benchmarks.\n\n\n## Quick Start\n\n### Installation\n\n```bash\ngit clone https://github.com/Protocol-Lattice/go-agent.git\ncd lattice-agent\ngo mod download\n```\n\n### Basic Usage\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"log\"\n\n\t\"github.com/Protocol-Lattice/go-agent/src/adk\"\n\tadkmodules \"github.com/Protocol-Lattice/go-agent/src/adk/modules\"\n\t\"github.com/Protocol-Lattice/go-agent\"\n\t\"github.com/Protocol-Lattice/go-agent/src/subagents\"\n\n\t\"github.com/Protocol-Lattice/go-agent/src/memory\"\n\t\"github.com/Protocol-Lattice/go-agent/src/memory/engine\"\n\t\"github.com/Protocol-Lattice/go-agent/src/models\"\n\t\"github.com/Protocol-Lattice/go-agent/src/tools\"\n)\n\nfunc main() {\n\tqdrantURL := flag.String(\"qdrant-url\", \"http://localhost:6333\", \"Qdrant base URL\")\n\tqdrantCollection := flag.String(\"qdrant-collection\", \"adk_memories\", \"Qdrant collection name\")\n\tflag.Parse()\n\tctx := context.Background()\n\n\t// --- Shared runtime\n\tresearcherModel, err := models.NewGeminiLLM(ctx, \"gemini-2.5-pro\", \"Research summary:\")\n\tif err != nil {\n\t\tlog.Fatalf(\"create researcher model: %v\", err)\n\t}\n\tmemOpts := engine.DefaultOptions()\n\n\tadkAgent, err := adk.New(ctx,\n\t\tadk.WithDefaultSystemPrompt(\"You orchestrate a helpful assistant team.\"),\n\t\tadk.WithSubAgents(subagents.NewResearcher(researcherModel)),\n\t\tadk.WithModules(\n\t\t\tadkmodules.NewModelModule(\"gemini-model\", func(_ context.Context) (models.Agent, error) {\n\t\t\t\treturn models.NewGeminiLLM(ctx, \"gemini-2.5-pro\", \"Swarm orchestration:\")\n\t\t\t}),\n\t\t\tadkmodules.InQdrantMemory(100000, *qdrantURL, *qdrantCollection, memory.AutoEmbedder(), \u0026memOpts),\n\t\t),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tagent, err := adkAgent.BuildAgent(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Use the agent\n\tresp, err := agent.Generate(ctx, \"SessionID\", \"What is pgvector\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tlog.Println(resp)\n}\n```\n\n### Running Examples\n\n```bash\n# Interactive CLI demo\ngo run cmd/demo/main.go\n\n# Multi-agent coordination\ngo run cmd/team/main.go\n\n# Quick start example\ngo run cmd/quickstart/main.go\n\n# CodeMode + Agent as UTCP Tool\ngo run cmd/example/codemode/main.go\n\n# Multi-Agent Workflow Orchestration\ngo run cmd/example/codemode_utcp_workflow/main.go\n\n# Agent-to-Agent Communication via UTCP\ngo run cmd/example/agent_as_tool/main.go\ngo run cmd/example/agent_as_utcp_codemode/main.go\n\n# Agent State Persistence (Checkpoint/Restore)\ngo run cmd/example/checkpoint/main.go\n```\n\n#### Example Descriptions\n\n- **`cmd/example/codemode/main.go`**: Demonstrates how to use CodeMode to enable agents to call UTCP tools (including other agents) via generated Go code. Shows the pattern: User Input → LLM generates `codemode.CallTool()` → UTCP executes tool.\n\n- **`cmd/example/codemode_utcp_workflow/main.go`**: Shows orchestrating multi-step workflows where multiple specialist agents (analyst, writer, reviewer) work together through UTCP tool calls.\n\n- **`cmd/example/agent_as_tool/main.go`**: Demonstrates exposing agents as UTCP tools using `RegisterAsUTCPProvider()`, enabling agent-to-agent communication and hierarchical agent architectures.\n- **`cmd/example/agent_as_utcp_codemode/main.go`**: Shows an agent exposed as a UTCP tool and orchestrated via CodeMode, illustrating natural language to tool call generation.\n- **`cmd/example/checkpoint/main.go`**: Demonstrates how to checkpoint an agent's state to disk and restore it later, preserving conversation history and shared space memberships.\n\n\n## Project Structure\n\n```\nlattice-agent/\n├── cmd/\n│   ├── demo/          # Interactive CLI with tools, delegation, and memory\n│   ├── quickstart/    # Minimal getting-started example\n│   └── team/          # Multi-agent coordination demos\n├── pkg/\n│   ├── adk/           # Agent Development Kit and module system\n│   ├── memory/        # Memory engine and vector store adapters\n│   ├── models/        # LLM provider adapters (Gemini, Ollama, Anthropic)\n│   ├── subagents/     # Pre-built specialist agent personas\n├── └── tools/         # Built-in tools (echo, calculator, time, etc.)\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description | Required |\n|----------|-------------|----------|\n| `GOOGLE_API_KEY` | Gemini API credentials | For Gemini models |\n| `GEMINI_API_KEY` | Alternative to `GOOGLE_API_KEY` | For Gemini models |\n| `DATABASE_URL` | PostgreSQL connection string | For persistent memory |\n| `ADK_EMBED_PROVIDER` | Embedding provider override | No (defaults to Gemini) |\n\n### Example Configuration\n\n```bash\nexport GOOGLE_API_KEY=\"your-api-key-here\"\nexport DATABASE_URL=\"postgres://user:pass@localhost:5432/lattice?sslmode=disable\"\nexport ADK_EMBED_PROVIDER=\"gemini\"\n```\n\n## Core Concepts\n\n### Memory Engine\n\nLattice includes a sophisticated memory system with retrieval-augmented generation (RAG):\n\n```go\nstore := memory.NewInMemoryStore() // or PostgreSQL/Qdrant\nengine := memory.NewEngine(store, memory.Options{}).\n    WithEmbedder(yourEmbedder)\n\nsessionMemory := memory.NewSessionMemory(\n    memory.NewMemoryBankWithStore(store), \n    8, // context window size\n).WithEngine(engine)\n```\n\nFeatures:\n- **Importance Scoring** – Automatically weights memories by relevance\n- **MMR Retrieval** – Maximal Marginal Relevance for diverse results\n- **Auto-Pruning** – Removes stale or low-value memories\n- **Multiple Backends** – In-memory, PostgreSQL+pgvector,mongodb, neo4j or Qdrant\n\n### Tool System\n\nCreate custom tools by implementing a simple interface:\n\n```go\npackage tools\n\nimport (\n        \"context\"\n        \"fmt\"\n        \"strings\"\n\n        \"github.com/Protocol-Lattice/go-agent\"\n)\n\n// EchoTool repeats the provided input. Useful for testing tool wiring.\ntype EchoTool struct{}\n\nfunc (e *EchoTool) Spec() agent.ToolSpec {\n        return agent.ToolSpec{\n                Name:        \"echo\",\n                Description: \"Echoes the provided text back to the caller.\",\n                InputSchema: map[string]any{\n                        \"type\": \"object\",\n                        \"properties\": map[string]any{\n                                \"input\": map[string]any{\n                                        \"type\":        \"string\",\n                                        \"description\": \"Text to echo back.\",\n                                },\n                        },\n                        \"required\": []any{\"input\"},\n                },\n        }\n}\n\nfunc (e *EchoTool) Invoke(_ context.Context, req agent.ToolRequest) (agent.ToolResponse, error) {\n        raw := req.Arguments[\"input\"]\n        if raw == nil {\n                return agent.ToolResponse{Content: \"\"}, nil\n        }\n        return agent.ToolResponse{Content: strings.TrimSpace(fmt.Sprint(raw))}, nil\n}\n```\n\nRegister tools with the module system and they're automatically available to all agents.\n\n### Multi-Agent Coordination\n\nUse **Shared Spaces** to coordinate multiple agents with shared memory\n\nPerfect for:\n- Team-based workflows where agents need shared context\n- Complex tasks requiring specialist coordination\n- Projects with explicit access control requirements\n\n### Agent Composability\n\nLattice treats Agents as first-class Tools. This allows you to expose any agent as a tool to another agent, enabling powerful hierarchical or mesh architectures.\n\n**Why use this?**\n- **Specialization**: Create small, focused agents (e.g., \"Researcher\", \"Coder\", \"Reviewer\") and orchestrate them with a \"Manager\" agent.\n- **Encapsulation**: Hide complex multi-step workflows behind a simple natural language interface.\n- **Scalability**: Build complex systems by composing simple, testable agents.\n\n### How It Works\n\nWhen you wrap an agent as a tool:\n1. **Context Isolation**: The sub-agent runs in its own session (namespaced like `parent_session.sub.tool_name`). It has its own memory and history, preventing the parent's context window from being polluted with the sub-agent's internal thought process.\n2. **Recursive Capability**: Since a sub-agent is just a tool, it can have its own tools—including *other* agents. This allows for arbitrarily deep hierarchies (e.g., CEO -\u003e CTO -\u003e Lead Dev -\u003e Coder).\n3. **Standard Interface**: The parent agent doesn't know it's talking to another AI. It simply sees a tool that takes an instruction and returns a result. This means you can swap a \"Researcher Agent\" with a \"Google Search Tool\" without changing the parent's logic.\n\n```go\n// 1. Create a specialist agent\nresearcher, _ := agent.New(agent.Options{\n    SystemPrompt: \"You are a researcher. Search for facts.\",\n    // ...\n})\n\n// 2. Create a manager agent that uses the researcher\nmanager, _ := agent.New(agent.Options{\n    SystemPrompt: \"You are a manager. Delegate tasks.\",\n    Tools: []agent.Tool{\n        // Expose the researcher as a tool!\n        researcher.AsTool(\"researcher\", \"Delegates research tasks to the specialist.\"),\n    },\n})\n\n// 3. The manager can now call the researcher tool\n// User: \"Find out why the sky is blue\"\n// Manager -\u003e calls tool \"researcher\" -\u003e Researcher Agent runs -\u003e returns result -\u003e Manager answers\n```\n\n### Exposing Agents as UTCP Tools\n\nIn addition to the internal `Tool` interface, Lattice agents can be exposed as **Universal Tool Calling Protocol (UTCP)** tools. This allows them to be consumed by any UTCP-compliant client, enabling cross-language and cross-platform agent orchestration.\n\n**Key Functions:**\n\n- `agent.AsUTCPTool(name, description)`: Wraps an agent as a standalone UTCP `tools.Tool` struct.\n- `agent.RegisterAsUTCPProvider(ctx, client, name, description)`: Automatically registers the agent as a tool provider on a UTCP client.\n\n**Example:**\n\n```go\n// 1. Create your specialist agent\nresearcher, _ := agent.New(agent.Options{\n    SystemPrompt: \"You are a researcher.\",\n})\n\n// 2. Initialize a UTCP client\nclient, err := utcp.NewUTCPClient(ctx, nil, nil, nil)\nif err != nil {\n    log.Fatal(err)\n}\n\n// 3. Register the agent as a UTCP provider\n// This makes the agent available as a tool named \"researcher.agent\"\nerr := researcher.RegisterAsUTCPProvider(ctx, client, \"researcher.agent\", \"Deep research agent\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// 4. Call the agent via UTCP\n// The tool accepts 'instruction' and optional 'session_id'\nresult, err := client.CallTool(ctx, \"researcher.agent\", map[string]any{\n    \"instruction\": \"Analyze the latest trends in AI agents\",\n}, \"researcher\", nil)\n\nfmt.Println(result[\"response\"])\n```\n\n**Benefits:**\n- **Interoperability**: Your Go agents can be called by Python scripts, CLI tools, or other systems using UTCP.\n- **Standardization**: Uses the standard UTCP schema for inputs and outputs.\n- **Zero Overhead**: Uses an in-process transport when running within the same Go application, avoiding network latency.\n\n### Agent State Persistence\n\nLattice supports **Checkpointing and Restoration**, allowing you to pause agents mid-task, persist their state to disk or a database, and resume them later (even after a crash or restart).\n\n**Key Methods:**\n- `agent.Checkpoint()`: Serializes the agent's state (system prompt, short-term memory, shared space memberships) to a `[]byte`.\n- `agent.Restore(data []byte)`: Rehydrates an agent instance from a checkpoint.\n\n**Example:**\n\n```go\n// 1. Checkpoint the agent\ndata, err := agent.Checkpoint()\nif err != nil {\n    log.Fatal(err)\n}\n// Save 'data' to file/DB...\n\n// 2. Restore the agent (later or after crash)\n// Create a fresh agent instance first\nnewAgent, err := agent.New(opts) \nif err != nil {\n    log.Fatal(err)\n}\n\n// Restore state\nif err := newAgent.Restore(data); err != nil {\n    log.Fatal(err)\n}\n// newAgent now has the same memory and context as the original\n```\n\n## Why Use TOON?\n\n**Token-Oriented Object Notation (TOON)** is integrated into Lattice to dramatically reduce token consumption when passing structured data to and from LLMs. This is especially critical for AI agent workflows where context windows are precious and API costs scale with token usage.\n\n### The Problem with JSON\n\nTraditional JSON is verbose and wastes tokens on repetitive syntax. Consider passing agent memory or tool responses:\n\n```json\n{\n  \"memories\": [\n    { \"id\": 1, \"content\": \"User prefers Python\", \"importance\": 0.9, \"timestamp\": \"2025-01-15\" },\n    { \"id\": 2, \"content\": \"User is building CLI tools\", \"importance\": 0.85, \"timestamp\": \"2025-01-14\" },\n    { \"id\": 3, \"content\": \"User works with PostgreSQL\", \"importance\": 0.8, \"timestamp\": \"2025-01-13\" }\n  ]\n}\n```\n\n**Token count:** ~180 tokens\n\n### The TOON Solution\n\nTOON compresses the same data by eliminating redundancy:\n\n```\nmemories[3]{id,content,importance,timestamp}:\n1,User prefers Python,0.9,2025-01-15\n2,User is building CLI tools,0.85,2025-01-14\n3,User works with PostgreSQL,0.8,2025-01-13\n```\n\n**Token count:** ~85 tokens\n\n**Savings: ~53% fewer tokens**\n\n### Why This Matters for AI Agents\n\n1. **Larger Context Windows** – Fit more memories, tool results, and conversation history into the same context limit\n2. **Lower API Costs** – Reduce your LLM API bills by up to 50% on structured data\n3. **Faster Processing** – Fewer tokens mean faster inference times and lower latency\n4. **Better Memory Systems** – Store and retrieve more historical context without hitting token limits\n5. **Multi-Agent Communication** – Pass more information between coordinating agents efficiently\n\n### When TOON Shines\n\nTOON is particularly effective for:\n\n- **Agent Memory Banks** – Retrieving and formatting conversation history\n- **Tool Responses** – Returning structured data from database queries or API calls\n- **Multi-Agent Coordination** – Sharing state between specialist agents\n- **Batch Operations** – Processing multiple similar records (users, tasks, logs)\n- **RAG Contexts** – Injecting retrieved documents with metadata\n\n### Example: Memory Retrieval\n\nWhen your agent queries its memory system, TOON can encode dozens of memories in the space where JSON would fit only a handful:\n\n```go\n// Retrieve memories\nmemories := sessionMemory.Retrieve(ctx, \"user preferences\", 20)\n\n// Encode with TOON for LLM context\nencoded, _ := toon.Marshal(memories, toon.WithLengthMarkers(true))\n\n// Pass to LLM with 40-60% fewer tokens than JSON\nprompt := fmt.Sprintf(\"Based on these memories:\\n%s\\n\\nAnswer the user's question.\", encoded)\n```\n\n### Human-Readable Format\n\nDespite its compactness, TOON remains readable for debugging and development. The format explicitly declares its schema, making it self-documenting:\n\n```\nusers[2]{id,name,role}:\n1,Alice,admin\n2,Bob,user\n```\n\nYou can immediately see: 2 users, with fields id/name/role, followed by their values.\n\n### Getting Started with TOON\n\nLattice automatically uses TOON for internal data serialization. To use it in your custom tools or memory adapters:\n\n```go\nimport \"github.com/toon-format/toon-go\"\n\n// Encode your structs\nencoded, err := toon.Marshal(data, toon.WithLengthMarkers(true))\n\n// Decode back to structs\nvar result MyStruct\nerr = toon.Unmarshal(encoded, \u0026result)\n\n// Or decode to dynamic maps\nvar doc map[string]any\nerr = toon.Unmarshal(encoded, \u0026doc)\n```\n\nFor more details, see the [TOON specification](https://github.com/toon-format/spec/blob/main/SPEC.md).\n\n---\n\n**Bottom Line:** TOON helps your agents do more with less, turning token budgets into a competitive advantage rather than a constraint.\n\n## 🧠 Tool Orchestrator (LLM-Driven UTCP Tool Selection)\n\nThe **Tool Orchestrator** is an intelligent decision engine that lets the LLM choose when and how to call UTCP tools.\nIt analyzes user input, evaluates available tools, and returns a structured JSON plan describing the next action.\n\n\u003e This brings `go-agent` to the same capability tier as OpenAI’s *tool choice*, but with fully pluggable **UTCP** backends and Go-native execution.\n\n---\n\n### 🎯 What It Does\n\n* Interprets the user’s request\n* Loads and renders all available UTCP tools\n* Allows the LLM to reason using **TOON-Go**\n* Produces a strict JSON decision object:\n\n  ```json\n  {\n    \"use_tool\": true,\n    \"tool_name\": \"search.files\",\n    \"arguments\": { \"query\": \"config\" },\n    \"reason\": \"User asked to look for configuration files\"\n  }\n  ```\n* Executes the chosen tool deterministically\n\n---\n\n### ⚙️ How It Works\n\n1. **Collect Tool Definitions**\n\n   ```go\n   rendered := a.renderUtcpToolsForPrompt()\n   ```\n\n2. **Build the Orchestration Prompt**\n\n   ```go\n   choicePrompt := fmt.Sprintf(`\n     You are a UTCP tool selection engine.\n\n     A user asked:\n     %q\n\n     You have access to these UTCP tools:\n     %s\n\n     You can also discover tools dynamically using:\n     search_tools(\"\u003cquery\u003e\", \u003climit\u003e)\n\n     Return ONLY JSON:\n     { \"use_tool\": ..., \"tool_name\": \"...\", \"arguments\": { }, \"reason\": \"...\" }\n   `, userInput, rendered)\n   ```\n\n3. **LLM Makes a Decision (via TOON)**\n\n   * Coordinator executes reasoning\n   * Assistant returns the final JSON only\n\n4. **Agent Executes the Tool**\n\n   * `CallTool`\n   * `SearchTools`\n   * `CallToolStream`\n\n5. **The result becomes the agent’s final response**\n\n---\n\n## 🧩 Why TOON-Go Improves Tool Selection\n\nThe orchestrator uses **TOON** as its structured reasoning layer:\n\n* Coordinator → analyzes tool options\n* Assistant → returns the strict JSON\n* No hallucinated formatting\n* Easy to debug via TOON traces\n* Session memory stores the entire reasoning trajectory\n\nThis yields **stable, deterministic** tool choice behavior.\n\n---\n\n## 🚀 Example\n\n### **User**\n\n\u003e find all files containing “db connection” in the workspace\n\n### **LLM Output**\n\n```json\n{\n  \"use_tool\": true,\n  \"tool_name\": \"search.files\",\n  \"arguments\": {\n    \"query\": \"db connection\",\n    \"limit\": 20\n  },\n  \"reason\": \"User wants to search through the workspace files\"\n}\n```\n\n### **Agent Execution**\n\nThe `search.files` UTCP tool is invoked, and its direct output is returned to the user.\n\n---\n\n---\n\n## 🧵 Works Seamlessly with CodeMode + Chain\n\n### **CodeMode**\n\nUTCP tool calls can run inside the Go DSL:\n\n```go\nr, _ := codemode.CallTool(\"echo\", map[string]any{\"input\": \"hi\"})\n```\n\n### **ChainStep**\n\nThe orchestrator can:\n\n* call a tool\n* run a chain step\n* discover tools dynamically\n* combine reasoning + execution\n\nThis makes `go-agent` one of the first Go frameworks with multi-step, LLM-driven tool-routing.\n\n\n## Development\n\n### Running Tests\n\n```bash\n# Run all tests\ngo test ./...\n\n# Run with coverage\ngo test -cover ./...\n\n# Run specific package tests\ngo test ./pkg/memory/...\n```\n\n### Code Style\n\nWe follow standard Go conventions:\n- Use `gofmt` for formatting\n- Follow [Effective Go](https://golang.org/doc/effective_go.html) guidelines\n- Add tests for new features\n- Update documentation when adding capabilities\n\n### Adding New Components\n\n**New LLM Provider:**\n1. Implement the `models.LLM` interface in `pkg/models/`\n2. Add provider-specific configuration\n3. Update documentation and examples\n\n**New Tool:**\n1. Implement `agent.Tool` interface in `pkg/tools/`\n2. Register with the tool module system\n3. Add tests and usage examples\n\n**New Memory Backend:**\n1. Implement `memory.VectorStore` interface\n2. Add migration scripts if needed\n3. Update configuration documentation\n\n## Prerequisites\n\n- **Go** 1.22+ (1.25 recommended)\n- **PostgreSQL** 15+ with `pgvector` extension (optional, for persistent memory)\n- **API Keys** for your chosen LLM provider\n\n### PostgreSQL Setup (Optional)\n\nFor persistent memory with vector search:\n\n```sql\nCREATE EXTENSION IF NOT EXISTS vector;\n```\n\nThe memory module handles schema migrations automatically.\n\n## Troubleshooting\n\n### Common Issues\n\n**Missing pgvector extension**\n```\nERROR: type \"vector\" does not exist\n```\nSolution: Run `CREATE EXTENSION vector;` in your PostgreSQL database.\n\n**API key errors**\n```\nERROR: authentication failed\n```\nSolution: Verify your API key is correctly set in the environment where you run the application.\n\n**Tool not found**\n```\nERROR: tool \"xyz\" not registered\n```\nSolution: Ensure tool names are unique and properly registered in your tool catalog.\n\n### Getting Help\n\n- Check existing [GitHub Issues](https://github.com/Protocol-Lattice/go-agent/issues)\n- Review the [examples](./cmd/) for common patterns\n- Join discussions in [GitHub Discussions](https://github.com/Protocol-Lattice/go-agent/discussions)\n\n## Contributing\n\nWe welcome contributions! Here's how to get started:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes with tests\n4. Update documentation\n5. Submit a pull request\n\nPlease ensure:\n- Tests pass (`go test ./...`)\n- Code is formatted (`gofmt`)\n- Documentation is updated\n- Commit messages are clear\n\n## License\n\nThis project is licensed under the [Apache 2.0 License](./LICENSE).\n\n## Acknowledgments\n\n- Inspired by Google's [Agent Development Kit (Python)](https://github.com/google/adk-python)\n\n---\n\n**Star us on GitHub** if you find Lattice useful! ⭐\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprotocol-lattice%2Fgo-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprotocol-lattice%2Fgo-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprotocol-lattice%2Fgo-agent/lists"}