chore: initial scaffold with design docs
This commit is contained in:
commit
c21173a7f8
12 changed files with 757 additions and 0 deletions
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -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.
|
||||
137
README.md
Normal file
137
README.md
Normal file
|
|
@ -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)
|
||||
93
docs/README.md
Normal file
93
docs/README.md
Normal file
|
|
@ -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.
|
||||
29
examples/README.md
Normal file
29
examples/README.md
Normal file
|
|
@ -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
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module github.com/VictorVargas/go-llm-agent
|
||||
|
||||
go 1.26
|
||||
57
pkg/agent/README.md
Normal file
57
pkg/agent/README.md
Normal file
|
|
@ -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
|
||||
81
pkg/config/README.md
Normal file
81
pkg/config/README.md
Normal file
|
|
@ -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
|
||||
91
pkg/llm/README.md
Normal file
91
pkg/llm/README.md
Normal file
|
|
@ -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
|
||||
71
pkg/persona/README.md
Normal file
71
pkg/persona/README.md
Normal file
|
|
@ -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
|
||||
82
pkg/rag/README.md
Normal file
82
pkg/rag/README.md
Normal file
|
|
@ -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
|
||||
73
pkg/tools/README.md
Normal file
73
pkg/tools/README.md
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue