APM-Packages/omos-deep-dive.md
Tobias J. Endres 602f0958bd docs(blog): current drafts, fact-check review and image assets
- apm-omos-agent-teams-v3.md: main blogpost draft (German)
- omos-deep-dive.md: second blogpost on oh-my-opencode-slim capabilities
- blog-review.md: source-of-truth copy of the Ghost draft + numbered
  revision proposals from the Perplexity fact-check
- image assets referenced by the blogposts (.jpg/.png)
2026-08-23 18:29:59 +02:00

256 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.