Plattform erweitern
ollama-agent ist als Basis gedacht, die man für einen speziellen Workflow übernimmt und erweitert. Es gibt drei Erweiterungsebenen — von “kein Code” bis “eigenes Binary”.
Ebene 1: Skills (kein Code, kein Rebuild)
Abschnitt betitelt „Ebene 1: Skills (kein Code, kein Rebuild)“Ein Skill ist ein Ordner mit einer SKILL.md:
skills/└── mein-skill/ ├── SKILL.md └── scripts/ # optional └── helper.sh---name: mein-skilldescription: Ein kurzer Satz, den das Modell liest.triggers: [stichwort, anderes stichwort]---
# AnleitungWas das Modell tun soll, wenn der Skill geladen ist ...- Die Skill-Liste (nur Name + Beschreibung) steht kompakt im System-Prompt; der Body wird erst per
load_skill-Tool in den Kontext geholt — wichtig für kleine Modelle. triggersladen den Skill automatisch, wenn ein Stichwort im Input vorkommt (skills.auto_load_on_trigger).- Scripts sind nur ausführbar, wenn
skills.allow_scripts: truegesetzt ist, und nur wenn sie bei der Discovery imscripts/-Ordner gefunden wurden.
Ebene 2: MCP-Server (Konfiguration)
Abschnitt betitelt „Ebene 2: MCP-Server (Konfiguration)“Beliebige MCP-Server (stdio oder HTTP) in der Config eintragen — ihre Tools stehen dem Agent sofort zur Verfügung, mit Namen mcp_<server>_<tool>:
"mcp_servers": [ { "name": "files", "transport": "stdio", "command": "mcp-filesystem-server", "args": ["/pfad"], "tool_tags": ["tool_calling", "code"] }]tool_tags steuert, bei welchen Task-Kategorien die Tools dem Modell angeboten werden (Tool-Subsetting hält die Prompts klein).
Ebene 3: Eigenes Binary (Go-Library)
Abschnitt betitelt „Ebene 3: Eigenes Binary (Go-Library)“Der gesamte Kern liegt unter pkg/ und ist importierbar. Minimalbeispiel für einen eigenen Workflow mit eigenem nativen Tool:
package main
import ( "context" "encoding/json" "log/slog"
"gitlab.techeve.de/techeve/ollama-agent/pkg/agent" "gitlab.techeve.de/techeve/ollama-agent/pkg/config" "gitlab.techeve.de/techeve/ollama-agent/pkg/pool" "gitlab.techeve.de/techeve/ollama-agent/pkg/router" "gitlab.techeve.de/techeve/ollama-agent/pkg/tools")
func main() { cfg, _ := config.Load("config.json") ctx := context.Background()
p := pool.New(cfg, slog.Default()) p.Start(ctx) defer p.Close()
reg := tools.NewRegistry() reg.Register(&tools.Func{ ToolName: "ticket_lookup", Desc: "Look up a support ticket by id.", ArgsSchema: json.RawMessage(`{ "type":"object", "properties":{"id":{"type":"string"}}, "required":["id"] }`), ToolTags: []string{"tool_calling"}, Fn: func(ctx context.Context, args json.RawMessage) (string, error) { // eigene Logik ... return "Ticket 42: offen, Priorität hoch", nil }, })
a := agent.New(agent.Options{ Pool: p, Tools: reg, Router: router.New(p, cfg.Models, nil), Config: cfg.Agent, })
res, _ := a.Run(ctx, "Wie ist der Status von Ticket 42?", agent.RunOptions{}) println(res.Output)}Bausteine und ihre Aufgaben:
| Paket | Aufgabe |
|---|---|
pkg/pool | Endpoint-Pool: Health-Checks, modell-bewusste Auswahl, Failover |
pkg/router | Task-Kategorie → Modell (Heuristik + LLM-Classify + Config) |
pkg/agent | Tool-Calling-Loop, Salvage-Parser, History-Kompaktierung, Sessions |
pkg/tools | Tool-Interface + Registry mit Kategorie-Tags |
pkg/skills | SKILL.md-Discovery und -Matching |
pkg/mcpclient | MCP-Server anbinden, Tools adaptieren |
pkg/sched | Cron-Jobs, die Agent-Läufe triggern |
pkg/api | HTTP-Daemon über allem |
Eigene Tools implementieren das Interface tools.Tool (oder nutzen tools.Func). Wichtig für kleine Modelle:
- Description: genau ein kurzer Satz.
- Schema: flach halten, wenige Pflichtfelder.
- Tags: Kategorien angeben, damit das Tool nur bei passenden Tasks im Prompt landet.
- Ergebnis: kompakt zurückgeben; der Loop truncated bei
max_tool_result_chars.