257 lines
8.9 KiB
Markdown
257 lines
8.9 KiB
Markdown
|
|
# Was oh-my-opencode-slim wirklich kann – und was `omos` daraus machen sollte
|
|||
|
|
|
|||
|
|
*Von Modell-IDs bis Sandboxing: Die OMOS-Konfiguration ist mächtiger, als man denkt.*
|
|||
|
|
|
|||
|
|
Im ersten Teil haben wir beschrieben, wie ein APM-Package sein empfohlenes Team deklarieren kann. Dort haben wir `omos` als Übersetzer zwischen `team-profile.yaml` und OMOS-Presets vorgestellt – und dabei nur zwei Konfigurationsflächen genutzt: Modell-IDs und MCP/Skill-Allowlists.
|
|||
|
|
|
|||
|
|
Das war bewusst minimal. Aber OMOS kann deutlich mehr. Und `omos` sollte das nutzen.
|
|||
|
|
|
|||
|
|
## Was OMOS alles kann
|
|||
|
|
|
|||
|
|
Die vollständige Konfiguration von oh-my-opencode-slim geht weit über Presets hinaus. Hier die wichtigsten Features, die für Team-Pakete relevant sind:
|
|||
|
|
|
|||
|
|
### Custom Agents mit eigenen Prompts
|
|||
|
|
|
|||
|
|
OMOS kann unter `agents` eigene Subagenten definieren. Jeder braucht ein `model`, einen `prompt` und optional einen `orchestratorPrompt`, der dem Orchestrator sagt, wann er delegieren soll:
|
|||
|
|
|
|||
|
|
```jsonc
|
|||
|
|
{
|
|||
|
|
"agents": {
|
|||
|
|
"writer": {
|
|||
|
|
"model": "ollama/qwen3.6:35b-a3b-q4_K_M",
|
|||
|
|
"prompt": "Erstelle faktenbasierte Bewerbungsunterlagen. "
|
|||
|
|
+ "Nutze nur freigegebene Profilfakten. "
|
|||
|
|
+ "Erfinde keine Erfahrung. "
|
|||
|
|
+ "Lege Entwürfe in ShareLaTeX ab. "
|
|||
|
|
+ "Reiche niemals eine Bewerbung ein.",
|
|||
|
|
"orchestratorPrompt": "@writer\n"
|
|||
|
|
+ "- Rolle: Anschreiben und CV-Anpassungen erstellen\n"
|
|||
|
|
+ "- Delegiere nach qualifiziertem Stellen-Match\n"
|
|||
|
|
+ "- Liefere einen ShareLaTeX-Entwurf und offene Fragen"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Der `orchestratorPrompt` ist der Schlüssel: Er wird direkt in den Orchestrator-Prompt injiziert und bestimmt, **wann** der Orchestrator diesen Agenten aufruft. Ohne ihn weiß der Orchestrator nicht, dass es den Agenten gibt.
|
|||
|
|
|
|||
|
|
### Tool-Permissions: Echte Sandboxing
|
|||
|
|
|
|||
|
|
OMOS bietet pro Agent ein `permission`-Objekt, das auf Tool-Ebene durchgesetzt wird – nicht nur MCP-Allowlists, sondern auch OpenCode-Core-Tools:
|
|||
|
|
|
|||
|
|
```jsonc
|
|||
|
|
{
|
|||
|
|
"agents": {
|
|||
|
|
"researcher": {
|
|||
|
|
"model": "ollama/qwen3.5:9b",
|
|||
|
|
"permission": {
|
|||
|
|
"edit": "deny",
|
|||
|
|
"bash": "deny",
|
|||
|
|
"task": "deny",
|
|||
|
|
"webfetch": "allow",
|
|||
|
|
"websearch": "allow"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Das ist eine **echte Sandbox**. Der Researcher darf suchen und lesen, aber keine Dateien bearbeiten, keine Shell-Befehle ausführen und keine Subagenten spawnen. Das geht über `mcps` und `skills` hinaus und ist das, was wir im ersten Blogpost als „mehrere Schichten der Verteidigung" beschrieben haben.
|
|||
|
|
|
|||
|
|
Verfügbare Permission-Keys:
|
|||
|
|
|
|||
|
|
| Key | Was es kontrolliert |
|
|||
|
|
|-----|-------------------|
|
|||
|
|
| `read` | Dateien lesen |
|
|||
|
|
| `edit` | Dateien bearbeiten |
|
|||
|
|
| `bash` | Shell-Befehle ausführen |
|
|||
|
|
| `task` | Subagenten delegieren |
|
|||
|
|
| `webfetch` | Web-Inhalte abrufen |
|
|||
|
|
| `websearch` | Websuche |
|
|||
|
|
| `glob` | Dateisuche nach Pattern |
|
|||
|
|
| `grep` | Inhaltsuche |
|
|||
|
|
| `skill` | Skill-Ausführung |
|
|||
|
|
|
|||
|
|
Jeder Key akzeptiert `"allow"`, `"deny"` oder `"ask"` (fragt den Nutzer). Für `bash` gibt es zusätzlich Pattern-basierte Regeln:
|
|||
|
|
|
|||
|
|
```jsonc
|
|||
|
|
"bash": {
|
|||
|
|
"*": "deny",
|
|||
|
|
"git status*": "allow",
|
|||
|
|
"git diff*": "allow"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Fallback-Ketten
|
|||
|
|
|
|||
|
|
OMOS unterstützt Modell-Failover bei 429-Errors (Rate Limiting). In der Mapping-Tabelle könnte man das so abbilden:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# ~/.config/apm-team/model-mapping.yaml
|
|||
|
|
model_classes:
|
|||
|
|
fast-research:
|
|||
|
|
primary: ollama/qwen3.5:9b
|
|||
|
|
fallback:
|
|||
|
|
- openai/gpt-4o-mini
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`omos` würde daraus ein OMOS-Array generieren:
|
|||
|
|
|
|||
|
|
```jsonc
|
|||
|
|
"librarian": {
|
|||
|
|
"model": ["ollama/qwen3.5:9b", "openai/gpt-4o-mini"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
OMOS versucht das erste Modell und wechselt bei Fehlern automatisch zum nächsten.
|
|||
|
|
|
|||
|
|
### Prompt-Dateien statt Inline-Prompts
|
|||
|
|
|
|||
|
|
Statt lange Prompts inline in die Config zu schreiben, kann man sie als Markdown-Dateien ablegen:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
.opencode/oh-my-opencode-slim/
|
|||
|
|
├── acme-job-applications/
|
|||
|
|
│ ├── writer.md # Preset-spezifisch
|
|||
|
|
│ └── researcher.md
|
|||
|
|
└── writer.md # Fallback für alle Presets
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Die Lookup-Reihenfolge ist:
|
|||
|
|
1. `.opencode/oh-my-opencode-slim/<preset>/<agent>.md` (projektspezifisch, preset-spezifisch)
|
|||
|
|
2. `.opencode/oh-my-opencode-slim/<agent>.md` (projektspezifisch, preset-übergreifend)
|
|||
|
|
3. `~/.config/opencode/oh-my-opencode-slim/<preset>/<agent>.md` (global, preset-spezifisch)
|
|||
|
|
4. `~/.config/opencode/oh-my-opencode-slim/<agent>.md` (global, preset-übergreifend)
|
|||
|
|
|
|||
|
|
`omos` könnte die `purpose`-Felder aus dem Team-Profil in solche Dateien schreiben – versionierbar im Package, geteilt über Presets.
|
|||
|
|
|
|||
|
|
### Weitere relevante Features
|
|||
|
|
|
|||
|
|
| Feature | OMOS-Feld | Nutzen für Teams |
|
|||
|
|
|---------|-----------|-----------------|
|
|||
|
|
| **Council** | `council.presets` | Mehrere Modelle parallel für kritische Entscheidungen (z.B. Checker) |
|
|||
|
|
| **ACP Agents** | `acpAgents.<name>` | Externe Agent-CLIs (Claude Code, Gemini) als Subagent einbinden |
|
|||
|
|
| **Multiplexer** | `multiplexer.type` | tmux/zellij-Panes für Live-Beobachtung arbeitender Agenten |
|
|||
|
|
| **displayName** | `displayName` | Alias für den Orchestrator (bereits im ersten Blogpost genutzt) |
|
|||
|
|
| **description** | `description` | Beschreibung, die dem Orchestrator bei der Routing-Entscheidung hilft |
|
|||
|
|
| **disabled_agents** | `disabled_agents[]` | Agenten global deaktivieren (z.B. Observer) |
|
|||
|
|
| **Background Jobs** | `backgroundJobs.*` | Orchestrator-Wake, Wall-Timeout für Hintergrundaufgaben |
|
|||
|
|
|
|||
|
|
## Was `omos` daraus machen sollte
|
|||
|
|
|
|||
|
|
Im ersten Blogpost haben wir `omos` als Übersetzer von Modellklassen und MCP-Allowlists beschrieben. Das war Phase 1. Hier ist, was Phase 2 und 3 aussehen:
|
|||
|
|
|
|||
|
|
### Phase 2: Custom Agents + Permissions
|
|||
|
|
|
|||
|
|
`omos` liest das Team-Profil und generiert für jeden Custom Agent (also jeden, der nicht auf einen eingebauten OMOS-Agenten mapped) einen vollständigen Agent-Block:
|
|||
|
|
|
|||
|
|
**Input** (team-profile.yaml):
|
|||
|
|
```yaml
|
|||
|
|
- id: writer
|
|||
|
|
purpose: Erstellt auf Fakten basierende Anschreiben und Lebensläufe in ShareLaTeX.
|
|||
|
|
Nutze nur freigegebene Profilfakten. Erfinde keine Erfahrung.
|
|||
|
|
omos_agent: custom
|
|||
|
|
model_class: strong-writing
|
|||
|
|
capabilities:
|
|||
|
|
mcps: [openviking, sharelatex]
|
|||
|
|
skills: []
|
|||
|
|
permissions:
|
|||
|
|
edit: deny
|
|||
|
|
bash: deny
|
|||
|
|
task: deny
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Output** (OMOS-Preset):
|
|||
|
|
```jsonc
|
|||
|
|
"writer": {
|
|||
|
|
"model": "ollama/qwen3.6:35b-a3b-q4_K_M",
|
|||
|
|
"prompt": "Erstellt auf Fakten basierende Anschreiben und Lebensläufe in ShareLaTeX. Nutze nur freigegebene Profilfakten. Erfinde keine Erfahrung.",
|
|||
|
|
"orchestratorPrompt": "@writer\n- Rolle: Anschreiben und CV erstellen\n- Delegiere nach qualifiziertem Stellen-Match",
|
|||
|
|
"mcps": ["openviking", "sharelatex"],
|
|||
|
|
"skills": [],
|
|||
|
|
"permission": {
|
|||
|
|
"edit": "deny",
|
|||
|
|
"bash": "deny",
|
|||
|
|
"task": "deny"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Phase 3: Prompt-Dateien + Fallback + Council
|
|||
|
|
|
|||
|
|
`omos` schreibt zusätzlich:
|
|||
|
|
- `.opencode/oh-my-opencode-slim/acme-job-applications/writer.md` mit dem vollständigen Prompt
|
|||
|
|
- Fallback-Ketten aus der Mapping-Tabelle
|
|||
|
|
- Optional: Council-Preset für den Checker (zwei Modelle parallel prüfen lassen)
|
|||
|
|
|
|||
|
|
## Die erweiterte Mapping-Tabelle
|
|||
|
|
|
|||
|
|
Für Phase 2 und 3 wird die Mapping-Tabelle reichhaltiger:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# ~/.config/apm-team/model-mapping.yaml
|
|||
|
|
model_classes:
|
|||
|
|
strong-generalist:
|
|||
|
|
primary: ollama/qwen3.6:35b-a3b-q4_K_M
|
|||
|
|
fallback:
|
|||
|
|
- openai/gpt-4o-mini
|
|||
|
|
|
|||
|
|
fast-research:
|
|||
|
|
primary: ollama/qwen3.5:9b
|
|||
|
|
fallback:
|
|||
|
|
- openai/gpt-4o-mini
|
|||
|
|
|
|||
|
|
strong-writing:
|
|||
|
|
primary: ollama/qwen3.6:35b-a3b-q4_K_M
|
|||
|
|
|
|||
|
|
high-reasoning:
|
|||
|
|
primary: ollama/qwen3.6:35b-a3b-q4_K_M
|
|||
|
|
variant: thinking
|
|||
|
|
options:
|
|||
|
|
thinking:
|
|||
|
|
type: enabled
|
|||
|
|
budgetTokens: 10000
|
|||
|
|
|
|||
|
|
cheap-reliable:
|
|||
|
|
primary: ollama/gemma4:12b
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`omos` übersetzt das deterministisch:
|
|||
|
|
- `primary` → erstes Modell im Array
|
|||
|
|
- `fallback` → weitere Einträge im Array
|
|||
|
|
- `variant` → wird direkt übernommen
|
|||
|
|
- `options` → wird direkt übernommen
|
|||
|
|
|
|||
|
|
## Was das für den Blogpost-Workflow bedeutet
|
|||
|
|
|
|||
|
|
Der erweiterte Flow sieht so aus:
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
P[APM Package: team-profile.yaml] --> O[omos liest]
|
|||
|
|
M[~/.config/apm-team/model-mapping.yaml] --> O
|
|||
|
|
O -->|Modellklassen| G[Generiere OMOS-Preset]
|
|||
|
|
O -->|purpose-Felder| PR[Generiere Prompt-Dateien]
|
|||
|
|
O -->|permissions| PE[Generiere Permission-Objekte]
|
|||
|
|
O -->|fallback| FB[Generiere Fallback-Ketten]
|
|||
|
|
G --> C[Schreibe .opencode/oh-my-opencode-slim.json]
|
|||
|
|
PR --> C
|
|||
|
|
PE --> C
|
|||
|
|
FB --> C
|
|||
|
|
C --> D[Fertig]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Fazit
|
|||
|
|
|
|||
|
|
OMOS ist nicht nur ein Preset-Switcher. Es ist ein vollständiges Agent-Konfigurationssystem mit Custom Prompts, Tool-Permissions, Fallback-Ketten und Multi-Model-Synthese. `omos` als Adapter sollte diese Möglichkeiten nutzen – nicht nur Modell-IDs übersetzen.
|
|||
|
|
|
|||
|
|
Die drei Phasen:
|
|||
|
|
|
|||
|
|
| Phase | Was omos generiert | OMOS-Features |
|
|||
|
|
|-------|-------------------|---------------|
|
|||
|
|
| **1** | Modell-IDs + MCP/Skill-Allowlists | `presets.<name>.<agent>.model`, `mcps`, `skills` |
|
|||
|
|
| **2** | + Custom Prompts + Permissions | `agents.<name>.prompt`, `orchestratorPrompt`, `permission` |
|
|||
|
|
| **3** | + Fallback-Ketten + Prompt-Dateien + Council | `model[]`, `.md`-Dateien, `council.presets` |
|
|||
|
|
|
|||
|
|
Phase 1 ist der Minimalprototyp. Phase 2 macht die Agenten wirklich arbeitsfähig. Phase 3 macht sie resilient.
|