From c21173a7f8e4781ed954d79f577431ca111f9447 Mon Sep 17 00:00:00 2001 From: Victor Vargas Date: Sun, 28 Jun 2026 16:03:57 -0700 Subject: [PATCH] chore: initial scaffold with design docs --- .gitignore | 19 ++++++ LICENSE | 21 +++++++ README.md | 137 ++++++++++++++++++++++++++++++++++++++++++ docs/README.md | 93 ++++++++++++++++++++++++++++ examples/README.md | 29 +++++++++ go.mod | 3 + pkg/agent/README.md | 57 ++++++++++++++++++ pkg/config/README.md | 81 +++++++++++++++++++++++++ pkg/llm/README.md | 91 ++++++++++++++++++++++++++++ pkg/persona/README.md | 71 ++++++++++++++++++++++ pkg/rag/README.md | 82 +++++++++++++++++++++++++ pkg/tools/README.md | 73 ++++++++++++++++++++++ 12 files changed, 757 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docs/README.md create mode 100644 examples/README.md create mode 100644 go.mod create mode 100644 pkg/agent/README.md create mode 100644 pkg/config/README.md create mode 100644 pkg/llm/README.md create mode 100644 pkg/persona/README.md create mode 100644 pkg/rag/README.md create mode 100644 pkg/tools/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4965a9b --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Go +*.exe +*.test +*.out +*.prof +vendor/ +coverage.out +coverage.html + +# Editor / OS +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Local build cache +.cache/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0d368bf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Victor Hugo Vargas Servín + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a3f2097 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# go-llm-agent + +> 🔑 **Librería core reutilizable** para construir agentes LLM en Go. + +Esta librería es el corazón de varios proyectos de Victor Vargas: +- [`harness`](https://github.com/VictorVargas/harness) — AI agent harness para desarrollo de software (TUI) +- [`chat-bot`](https://github.com/VictorVargas/chat-bot) — Chatbot HTTP para portfolios y sitios web + +Provee toda la lógica **genérica** de un agente LLM: + +| Componente | Ubicación | Responsabilidad | +|---|---|---| +| **Agent loop** | `pkg/agent/` | Bucle iterativo con guardrails | +| **LLM clients** | `pkg/llm/` | Abstracción multi-provider (OpenAI, Anthropic, Ollama) | +| **RAG / memoria** | `pkg/rag/` | Memoria de corto y largo plazo con búsqueda semántica | +| **Persona system** | `pkg/persona/` | System prompts configurables + AGENTS.md discovery | +| **Tool registry** | `pkg/tools/` | JSON Schema + execution sandbox | +| **Config loading** | `pkg/config/` | Carga de YAML con precedencia jerárquica | + +## 🎯 Filosofía + +- **Reusable, no opinionated.** No fuerza un tipo de UI, deployment, ni use case. +- **Hexagonal.** Ports & adapters permiten sustituir cualquier pieza. +- **Streaming-first.** Usa `iter.Seq2` de Go 1.23+ para streaming sin boilerplate. +- **Seguridad por defecto.** Sandbox de paths con `os.Root` (Go 1.24+). + +## 📦 Instalación + +```bash +go get github.com/VictorVargas/go-llm-agent +``` + +## 🔧 Setup del proyecto (si vas a contribuir) + +```bash +git clone https://github.com/VictorVargas/go-llm-agent.git +cd go-llm-agent + +# El go.mod ya existe con module + go version +# Las dependencias se agregan automáticamente cuando escribes código: + +# 1. Escribe tu código importando paquetes +# 2. Ejecuta: +go mod tidy # resuelve imports → actualiza go.mod + crea go.sum +``` + +## 🚀 Uso básico + +```go +package main + +import ( + "context" + "fmt" + "github.com/VictorVargas/go-llm-agent/pkg/agent" + "github.com/VictorVargas/go-llm-agent/pkg/llm" + "github.com/VictorVargas/go-llm-agent/pkg/persona" +) + +func main() { + // 1. Crear cliente LLM + llmClient, _ := llm.NewAnthropicClient(llm.AnthropicConfig{ + APIKey: os.Getenv("ANTHROPIC_API_KEY"), + Model: "claude-sonnet-4.5", + }) + + // 2. Cargar persona + p := persona.Load("./persona.yaml") + + // 3. Crear agent loop + loop := agent.New(agent.Config{ + LLM: llmClient, + Persona: p, + MaxIters: 50, + Sandbox: agent.NewSandbox("./workspace"), + }) + + // 4. Ejecutar + resp, err := loop.Run(context.Background(), "Refactoriza auth.go") + if err != nil { panic(err) } + + fmt.Println(resp.Content) +} +``` + +## 🔌 Adapters incluidos + +### LLM Providers (`pkg/llm/providers/`) + +| Provider | Import | Modelos | +|---|---|---| +| OpenAI | `llm/providers/openai` | gpt-4o, gpt-4o-mini, gpt-4-turbo | +| Anthropic | `llm/providers/anthropic` | claude-sonnet-4.5, claude-haiku-4 | +| Ollama | `llm/providers/ollama` | llama3.1, qwen2.5, mistral, etc. | +| llama.cpp | `llm/providers/llamacpp` | Custom GGUF models | + +### Vector DBs (`pkg/rag/backends/`) + +| Backend | Estado | +|---|---| +| ChromaDB embedded | ✅ Estable | +| Qdrant embedded | 🚧 En desarrollo | +| SQLite + sqlite-vec | 📋 Planeado | + +### Embeddings (`pkg/rag/embeddings/`) + +- Ollama embeddings (nomic-embed-text, bge-m3, etc.) +- Local sentence-transformers via ONNX + +## 🧪 Testing + +```bash +go test ./... +go test -race ./... +go test -bench=. ./pkg/agent/ +``` + +Incluye `MockLLMClient` para tests deterministas sin gastar API calls. + +## 📐 Versiones + +- **Go mínimo:** 1.26 (usa `os.Root`, `iter.Seq`, `unique.Handle`, container-aware GOMAXPROCS) +- **Política de versionado:** Semver estricto. API breaking changes solo en MAJOR. + +## 📄 Licencia + +MIT — ver [`LICENSE`](./LICENSE). + +## 🔗 Proyectos que usan esta librería + +- [`VictorVargas/harness`](https://github.com/VictorVargas/harness) — TUI agent para software dev +- [`VictorVargas/chat-bot`](https://github.com/VictorVargas/chat-bot) — HTTP chatbot + +## 📚 Documentación adicional + +- [Architecture overview](./docs/README.md) +- [Design decisions](./docs/architecture.md) (próximamente) \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..be12258 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,93 @@ +# go-llm-agent — Documentación + +Documentación técnica detallada de la librería. + +## 📐 Arquitectura + +``` +┌────────────────────────────────────────────────────────────────┐ +│ go-llm-agent (pkg/) │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ +│ │ agent │ │ persona │ │ tools │ │ +│ │ │ │ │ │ │ │ +│ │ Agent loop │◄─┤ Persona │ │ Tool registry │ │ +│ │ con guard- │ │ + AGENTS.md │ │ + JSON Schema │ │ +│ │ rails │ │ discovery │ │ + execution │ │ +│ └──────┬───────┘ └──────────────┘ └────────┬─────────┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ llm │ │ rag │ │ +│ │ │ │ │ │ +│ │ LLMClient │ │ Memory + │ │ +│ │ interface + │ │ Embeddings │ │ +│ │ providers │ │ + VectorDB │ │ +│ └──────────────┘ └──────────────┘ │ +│ │ +└────────────────────────────────────────────────────────────────┘ +``` + +## 📦 Paquetes + +| Paquete | Responsabilidad | Docs | +|---|---|---| +| `pkg/agent` | Bucle iterativo, termination conditions, approval gates | [Ver](../pkg/agent/README.md) | +| `pkg/llm` | `LLMClient` interface, streaming, providers | [Ver](../pkg/llm/README.md) | +| `pkg/rag` | Memoria, embeddings, búsqueda semántica | [Ver](../pkg/rag/README.md) | +| `pkg/persona` | System prompts, AGENTS.md, few-shot examples | [Ver](../pkg/persona/README.md) | +| `pkg/tools` | Tool registry, JSON Schema, sandboxing | [Ver](../pkg/tools/README.md) | +| `pkg/config` | YAML loading, precedence, env override | [Ver](../pkg/config/README.md) | + +## 🎯 Principios de diseño + +### 1. Streaming-first +Usa `iter.Seq2[T, error]` de Go 1.23+ para streaming natural: + +```go +for token, err := range llmClient.StreamTokens(ctx, req) { + if err != nil { return err } + fmt.Print(token) +} +``` + +### 2. Hexagonal puro +Cada paquete expone interfaces, las implementaciones concretas están separadas: + +```go +// pkg/rag/rag.go (puerto) +type VectorDB interface { + Search(ctx context.Context, embedding []float32, topK int) ([]Document, error) +} + +// pkg/rag/backends/chroma/chroma.go (adapter) +type ChromaDB struct { ... } +func (c *ChromaDB) Search(...) { ... } +``` + +### 3. Seguridad por defecto +- `os.Root` para sandbox de filesystem (Go 1.24+) +- Approval gates antes de tools destructivos +- Bash sandbox con denylist + timeout +- Network egress control opcional + +### 4. Zero magic +No hay reflection, no hay code generation, no hay DSLs. Todo es Go idiomático y explícito. + +## 🔄 Versionado + +- **Semver estricto** (`vMAJOR.MINOR.PATCH`) +- **MAJOR**: breaking changes en `pkg/` (interfaces, signatures, tipos públicos) +- **MINOR**: nuevas features, nuevos paquetes, nuevos adapters +- **PATCH**: bugfixes + +Los adapters privados (`pkg/llm/providers/openai/`) pueden cambiar sin bump de MAJOR si la interfaz `LLMClient` no cambia. + +## 🚧 Estado actual + +⚠️ **Esta librería está en diseño activo.** El código todavía no está implementado. La especificación completa está en los design docs de los proyectos que la consumen: + +- [`VictorVargas/harness/docs/architecture.md`](https://github.com/VictorVargas/harness/blob/main/docs/architecture.md) — Define los requirements +- [`VictorVargas/harness/docs/phase2.md`](https://github.com/VictorVargas/harness/blob/main/docs/phase2.md) — Features avanzadas + +Una vez que `harness/` esté implementado, esta librería se extraerá como código real. \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..f9e9660 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,29 @@ +# Examples + +> Ejemplos de uso de `go-llm-agent` en distintos contextos. + +## 📁 Contenido planeado + +| Ejemplo | Descripción | Estado | +|---|---|---| +| `simple_chat/` | Chat básico sin tools | 📋 Pendiente | +| `chat_with_tools/` | Chat con tools custom | 📋 Pendiente | +| `rag_qa/` | Q&A sobre documentos | 📋 Pendiente | +| `multi_agent/` | Orquestación de sub-agents | 📋 Pendiente | +| `streaming_ui/` | Integración con TUI | 📋 Pendiente | + +## 🎯 Cómo correr los ejemplos (cuando existan) + +```bash +cd examples/simple_chat +go mod tidy +export ANTHROPIC_API_KEY=sk-ant-... +go run main.go +``` + +## 📝 Contribuir + +Cada ejemplo debe ser: +- ✅ **Standalone**: `go run main.go` y funciona +- ✅ **Mínimo**: <100 líneas si es posible +- ✅ **Documentado**: README con qué demuestra y cómo extenderlo \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..183166a --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/VictorVargas/go-llm-agent + +go 1.26 \ No newline at end of file diff --git a/pkg/agent/README.md b/pkg/agent/README.md new file mode 100644 index 0000000..eb74308 --- /dev/null +++ b/pkg/agent/README.md @@ -0,0 +1,57 @@ +# pkg/agent + +> El bucle principal que ejecuta un agente LLM con guardrails. + +## Responsabilidad + +Coordinar el ciclo iterativo entre el LLM y la ejecución de tools: + +``` +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 +``` + +## API pública + +```go +type Loop interface { + Run(ctx context.Context, input string) (Response, error) + RunStream(ctx context.Context, input string) 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 +} +``` + +## Garantías + +- **Termination**: Siempre termina (max iterations, error, o respuesta final) +- **Idempotencia**: Re-ejecutar con el mismo input produce el mismo output (dado el mismo LLM) +- **Observabilidad**: Cada iteración emite un span OpenTelemetry +- **Approval**: Tool destructivos (`Ask` permission) requieren confirmación + +## Ver también + +- [pkg/tools](../tools/README.md) — Tool execution +- [pkg/llm](../llm/README.md) — LLMClient interface +- [pkg/persona](../persona/README.md) — Persona assembly \ No newline at end of file diff --git a/pkg/config/README.md b/pkg/config/README.md new file mode 100644 index 0000000..b5dc9c3 --- /dev/null +++ b/pkg/config/README.md @@ -0,0 +1,81 @@ +# pkg/config + +> Carga de configuración YAML con precedencia jerárquica. + +## Responsabilidad + +Resolver la configuración final del agente combinando múltiples fuentes con orden de precedencia: + +1. **Flags CLI** (highest) +2. **Environment variables** +3. **Project config** (`./.rony.yaml`) +4. **Global config** (`~/.config/rony/config.yaml`) +5. **Defaults embebidos** (lowest) + +## API pública + +```go +type Config struct { + Model string + Persona string + Provider ProviderConfig + Tools ToolPolicy + Logging LoggingConfig + Sandbox SandboxConfig +} + +type Loader interface { + Load(ctx context.Context, workdir string) (Config, error) + LoadFromBytes(data []byte, source string) (Config, error) +} + +type ProviderConfig struct { + Type string // "openai" | "anthropic" | "ollama" | "llamacpp" + Model string + APIKey string // resuelto de env si es referencia + Endpoint string +} + +type ToolPolicy map[string]tools.Permission +``` + +## Formato YAML + +```yaml +# ~/.config/rony/config.yaml +model: claude-sonnet-4.5 +persona: pragmatista +provider: + type: anthropic + api_key_env: ANTHROPIC_API_KEY +tools: + bash: ask + read: allow + write: ask +logging: + level: info + format: json +sandbox: + workspace: . + timeout_ms: 30000 +``` + +## Override por env + +```bash +RONY_MODEL=gpt-4o rony chat # override model +RONY_LOG_LEVEL=debug rony chat # override log level +``` + +## Precedencia + +El loader resuelve en este orden (mayor prioridad primero): + +``` +flag > RONY_* env > ./.rony.yaml > ~/.config/rony/config.yaml > defaults +``` + +## Ver también + +- [pkg/agent](../agent/README.md) — Usa Config +- [pkg/llm](../llm/README.md) — ProviderConfig se mapea a LLMClient \ No newline at end of file diff --git a/pkg/llm/README.md b/pkg/llm/README.md new file mode 100644 index 0000000..568a0c7 --- /dev/null +++ b/pkg/llm/README.md @@ -0,0 +1,91 @@ +# pkg/llm + +> Abstracción multi-provider para modelos de lenguaje. + +## Responsabilidad + +Definir una interfaz común (`LLMClient`) y adapters para los principales providers. + +## API pública + +```go +type LLMClient interface { + Generate(ctx context.Context, req CompletionRequest) (CompletionResponse, error) + Stream(ctx context.Context, req CompletionRequest) iter.Seq2[StreamChunk, error] + Name() string + Capabilities() ProviderCapabilities +} + +type CompletionRequest struct { + Messages []Message + Tools []tools.Tool + ToolChoice ToolChoice + Model string + Temperature *float32 + MaxTokens *int +} + +type CompletionResponse struct { + Content string + ToolCalls []tools.Call + Usage TokenUsage + StopReason string +} + +type ProviderCapabilities struct { + SupportsTools bool + SupportsVision bool + MaxContextWindow int +} +``` + +## Providers incluidos + +| Provider | Paquete | Soporte tools | +|---|---|---| +| OpenAI | `providers/openai` | ✅ | +| Anthropic | `providers/anthropic` | ✅ | +| Ollama | `providers/ollama` | ✅ (modelos que lo soporten) | +| llama.cpp | `providers/llamacpp` | ✅ (con grammar) | + +## Uso + +```go +import "github.com/VictorVargas/go-llm-agent/pkg/llm/providers/anthropic" + +client, err := anthropic.New(anthropic.Config{ + APIKey: os.Getenv("ANTHROPIC_API_KEY"), + Model: "claude-sonnet-4.5", +}) + +resp, err := client.Generate(ctx, llm.CompletionRequest{ + Messages: []llm.Message{ + {Role: llm.RoleUser, Content: "Hola"}, + }, +}) +``` + +## Streaming + +```go +for chunk, err := range client.Stream(ctx, req) { + if err != nil { return err } + fmt.Print(chunk.Delta) +} +``` + +## Mock para tests + +```go +import "github.com/VictorVargas/go-llm-agent/pkg/llm/mock" + +mockClient := mock.New(mock.Responses{ + {Match: "hola", Response: "¡Hola! ¿Cómo estás?"}, + {Match: "*", Response: "default"}, +}) +``` + +## Ver también + +- [pkg/agent](../agent/README.md) — Usa `LLMClient` +- [pkg/tools](../tools/README.md) — Las `Tool` definitions \ No newline at end of file diff --git a/pkg/persona/README.md b/pkg/persona/README.md new file mode 100644 index 0000000..a02abd7 --- /dev/null +++ b/pkg/persona/README.md @@ -0,0 +1,71 @@ +# pkg/persona + +> Sistema de personalidades configurables para agentes LLM. + +## Responsabilidad + +Ensamblar el system prompt final del agente combinando: + +1. **Base prompt** (hardcoded en la librería) +2. **Persona YAML** (configurable por proyecto) +3. **AGENTS.md** (instrucciones del proyecto, descubierto por búsqueda en árbol de directorios) +4. **Working memory context** (resúmenes si hay compaction) + +## API pública + +```go +type Persona struct { + ID string + Name string + Tone string + Style string + Language string + Constraints []string + FewShot []llm.Message +} + +type Loader interface { + Load(ctx context.Context, configPath string) (Persona, error) + Discover(ctx context.Context, workdir string) (Persona, error) // incluye AGENTS.md +} +``` + +## Formato YAML + +```yaml +id: pragmatista +name: Pragmatista +tone: "Directo y profesional" +style: "Enfoque Go idiomatic" +language: "Español, con términos técnicos en inglés" +constraints: + - "No usar interface{} en código nuevo" + - "Siempre wrapped errors con %w" +few_shot: + - role: user + content: "Refactoriza este código" + - role: assistant + content: "Listo. Optimizado. ¿Aplico?" +``` + +## AGENTS.md discovery + +El loader busca `./AGENTS.md`, sube al directorio padre, etc., concatenando todos los encontrados hasta llegar a `~` o `/`. También incluye `~/.config/rony/AGENTS.md` como default global. + +``` +/home/user/proyecto/AGENTS.md ← incluye +/home/user/AGENTS.md ← incluye +/home/AGENTS.md ← incluye +~/.config/rony/AGENTS.md ← incluye +``` + +## Uso + +```go +p, err := persona.Discover(ctx, "/home/user/mi-proyecto") +// p.Content incluye todo lo anterior concatenado +``` + +## Ver también + +- [pkg/agent](../agent/README.md) — Usa la persona en el system prompt \ No newline at end of file diff --git a/pkg/rag/README.md b/pkg/rag/README.md new file mode 100644 index 0000000..184947d --- /dev/null +++ b/pkg/rag/README.md @@ -0,0 +1,82 @@ +# pkg/rag + +> Retrieval-Augmented Generation: memoria, embeddings, y búsqueda semántica. + +## Responsabilidad + +Proveer memoria persistente y búsqueda semántica sobre el contenido del agente. + +## Componentes + +| Tipo | Qué guarda | Persistencia | +|---|---|---| +| **Working** | Mensajes de la sesión actual | RAM | +| **Episodic** | Eventos pasados (qué hice el día X) | Vector DB | +| **Semantic** | Conocimiento consolidado | Vector DB (curado) | +| **Procedural** | Patrones de uso (workflows) | Vector DB (auto-aprendido) | + +## API pública + +```go +type Memory interface { + Add(ctx context.Context, fragment Fragment) error + Search(ctx context.Context, query string, topK int) ([]Fragment, error) + Forget(ctx context.Context, id string) error +} + +type Fragment struct { + ID string + Content string + Vector []float32 + Metadata map[string]string + Timestamp time.Time + ProjectID string +} + +type Embedder interface { + Embed(ctx context.Context, text string) ([]float32, error) + Dimensions() int +} +``` + +## Backends + +| Backend | Cuándo usar | +|---|---| +| ChromaDB embedded | Default. Simple, suficiente para <100k docs | +| Qdrant embedded | Si necesitas >100k docs o queries muy rápidas | +| SQLite + sqlite-vec | Si quieres zero-dependency (sin CGO con `modernc.org/sqlite`) | + +## Embeddings + +| Provider | Modelo | Dimensiones | +|---|---|---| +| Ollama | `nomic-embed-text` | 768 | +| Ollama | `bge-m3` | 1024 | +| Local ONNX | `all-MiniLM-L6-v2` | 384 | + +## Uso + +```go +import "github.com/VictorVargas/go-llm-agent/pkg/rag" +import "github.com/VictorVargas/go-llm-agent/pkg/rag/backends/chroma" + +backend, _ := chroma.New(chroma.Config{ + Path: "~/.local/share/rony/chroma", +}) + +memory := rag.New(rag.Config{ + Backend: backend, + Embedder: ollamaEmbedder, +}) + +err := memory.Add(ctx, rag.Fragment{ + Content: "Refactoricé auth.go usando hexagonal", + ProjectID: "rony", +}) +``` + +## Ver también + +- [pkg/agent](../agent/README.md) — Inyecta memoria al loop +- [pkg/llm](../llm/README.md) — Para summarization en compaction \ No newline at end of file diff --git a/pkg/tools/README.md b/pkg/tools/README.md new file mode 100644 index 0000000..1d9cfae --- /dev/null +++ b/pkg/tools/README.md @@ -0,0 +1,73 @@ +# pkg/tools + +> Sistema de tools (function calling) con JSON Schema, sandbox, y permisos. + +## Responsabilidad + +Permitir que el LLM invoque funciones definidas en Go, con validación de schema y sandboxing. + +## API pública + +```go +type Tool struct { + Name string + Description string + InputSchema json.RawMessage // JSON Schema draft-07+ + Handler Handler // func(ctx, args json.RawMessage) (Result, error) + Permission Permission // Allow | Ask | Deny + Examples []Example // few-shot para el LLM +} + +type Registry interface { + Register(tool Tool) error + Get(name string) (Tool, bool) + List() []Tool + Filter(policy Policy) []Tool +} + +type Call struct { + ID string + Name string + Arguments json.RawMessage + Thought string // opcional: chain-of-thought del LLM +} + +type Result struct { + Content string + IsError bool + Metadata map[string]string + Artifacts []Artifact +} + +type Permission int + +const ( + Allow Permission = iota + Ask + Deny +) +``` + +## Sandbox integrado + +`pkg/tools` usa `os.Root` (Go 1.24+) para sandbox de filesystem: + +```go +sandbox := tools.NewSandbox("./workspace") +sandbox.Register(myReadTool) // solo puede leer dentro del workspace +``` + +Ver [pkg/tools/sandbox/](sandbox/) para detalles. + +## Tools genéricos incluidos + +- `http_fetch` — GET a URL con HTML→markdown +- `json_parse` — Parse JSON arbitrario +- `datetime_now` — Current timestamp + +Las tools específicas de cada producto (ej. `read_file`, `bash` para software dev) las define cada consumidor en su propio `internal/tools/`. + +## Ver también + +- [pkg/agent](../agent/README.md) — Ejecuta tool calls +- [pkg/llm](../llm/README.md) — Las tools se envían al LLM \ No newline at end of file