Tools
Plugin German Tutor
German tutoring agent plugin for OpenClaw โ CEFR-calibrated, scenario-based lessons with graduated corrections (Sprechi)
Configuration Example
"plugins": {
"entries": {
"german-tutor": {
"enabled": true,
"config": {
"agentId": "sprechi",
"activeProfile": "jae"
}
}
}
}
README
# Sprechi โ German Tutoring Agent for OpenClaw
An OpenClaw agent that conducts one-on-one German conversation lessons on
Discord. Sprechi speaks Hochdeutsch only, calibrates to the learner's CEFR
level, runs task-based scenarios, and corrects errors with graduated
reproduction prompts โ all grounded in second language acquisition research.
## What this directory contains
```
german-tutor/
โโโ README.md โ you are here
โโโ package.json โ npm package manifest
โโโ openclaw.plugin.json โ OpenClaw plugin registration + config schema
โโโ index.ts โ plugin entry point (registers the hook)
โโโ src/ โ plugin source code
โ โโโ config.ts โ config parser
โ โโโ profile.ts โ learner profile loader
โ โโโ scenarios.ts โ scenario loader
โ โโโ levels.ts โ CEFR level doc loader
โ โโโ prompt-inject.ts โ builds the context block
โโโ content/ โ all teaching content (edit these, not the code)
โโโ persona.md โ the 11 pedagogical principles
โโโ levels/ โ CEFR reference docs
โ โโโ A1.md
โ โโโ A2.md
โ โโโ B1.md
โโโ profiles/ โ learner profiles (one per student)
โ โโโ jae.json
โโโ scenarios/ โ 13 task-based scenarios
โโโ biergarten.json
โโโ bahnhof.json
โโโ ... (11 more)
```
## How it works
Sprechi is both a configured **agent** in OpenClaw and a **plugin** that
supplements that agent with German tutoring context. The two pieces work
together:
### The agent
- Defined in `openclaw.json` under `agents.list` as `sprechi`
- Has its own workspace at `~/.openclaw/workspace-sprechi/`
- The workspace contains `SOUL.md` โ Sprechi's core identity and
teaching philosophy that OpenClaw loads into the system prompt automatically
- Bound to one specific Discord channel via an entry in `bindings` โ any
message in that channel routes to `sprechi` instead of the default agent
- Threads inside that channel inherit the binding automatically
### The plugin
- Registered in `openclaw.json` under `plugins.entries.german-tutor`
- On every turn in Sprechi's channel, the plugin's `before_prompt_build`
hook fires and injects a context block in front of the system prompt
- The context block contains:
1. The full 11 pedagogical principles from `content/persona.md`
2. The CEFR reference document matching the learner's level (A1, A2, or B1)
3. A learner-context block summarizing the learner's profile
4. The current scenario (role, information gap, vocabulary, success criteria)
5. A correction-watch list of the learner's top recurring errors, each
tagged with priority and a specific action directive
The plugin guards on `ctx.agentId === "sprechi"` so it only activates for
this agent. Other OpenClaw agents are unaffected.
### Per-turn flow
```
User sends Discord message in bound channel
โ
โผ
OpenClaw routes to sprechi agent
โ
โผ
before_prompt_build hook fires
โ
โผ
Plugin loads profile + level doc + scenario + persona
โ
โผ
Plugin builds context block (~2500 tokens)
โ
โผ
Context block prepended to system prompt
โ
โผ
Agent call made with full context (persona + CEFR + profile + scenario)
โ
โผ
Response posted to Discord
โ
โผ
chatlog plugin logs the exchange to markdown
```
## Configuration
### Where things live
| What | Path |
|------|------|
| Main OpenClaw config | `~/.openclaw/openclaw.json` |
| Agent workspace (SOUL.md) | `~/.openclaw/workspace-sprechi/` |
| Plugin code + content | `~/openclaw/extensions/german-tutor/` |
| Extension logs | `~/.openclaw/logs/` and `/tmp/openclaw/openclaw-*.log` |
| Chatlog output | `~/.openclaw/chatlog/` (see chatlog plugin) |
### Plugin config in openclaw.json
```json
"plugins": {
"entries": {
"german-tutor": {
"enabled": true,
"config": {
"agentId": "sprechi",
"activeProfile": "jae"
}
}
}
}
```
- `agentId`: which agent the plugin activates for. Defaults to `sprechi`.
- `activeProfile`: which profile file to load from `content/profiles/`.
Defaults to `jae`. Set to `partner` to load `content/profiles/partner.json`.
### Agent registration
```json
"agents": {
"list": [
{
"id": "sprechi",
"name": "Sprechi",
"workspace": "/home/agentshik/.openclaw/workspace-sprechi"
}
]
}
```
### Channel binding
```json
"bindings": [
{
"agentId": "sprechi",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "1494366718292660224" }
}
}
]
```
Replace the channel ID to bind Sprechi to a different Discord channel.
---
## Common tasks
### Change the learner's current scenario
Edit the profile file and change `current_scenario` to any scenario ID
from `content/scenarios/`:
```bash
nano ~/openclaw/extensions/german-tutor/content/profiles/jae.json
```
```json
{
"current_scenario": "therapie", โ change this
...
}
```
Available scenario IDs: `biergarten`, `bahnhof`, `wohnung`, `arzt`,
`wegbeschreibung`, `cafe`, `reklamation`, `verabredung`, `party`,
`beschwerde`, `storepruefung`, `kita`, `therapie`.
**No restart needed** โ the plugin reads the profile on every turn.
### Change the learner's CEFR level
Edit the profile file:
```json
{
"cefr_level": "B1", โ change to A1, A2, or B1
"cefr_by_skill": {
"speaking": "B1",
"listening": "B1",
"reading": "B1",
"writing": "A2"
},
...
}
```
The plugin will automatically load `content/levels/B1.md` instead of A2.
### Update recurring errors
After a tutoring session, update `recurring_errors` in the profile so
Sprechi knows what to watch for:
```json
"recurring_errors": [
{
"pattern": "Drops articles before nouns in casual speech",
"priority": "critical",
"principle": "P4",
"action": "correct EVERY time"
},
{
"pattern": "Your new pattern here",
"priority": "high", โ critical | high | medium | low
"principle": "P5", โ which principle applies
"action": "explicit correction + reproduction"
}
]
```
Priority order: `critical` > `high` > `medium` > `low`. Keep the list
short โ 3-5 items max. Too many and Sprechi will over-correct.
### Add a new scenario
Create a new JSON file in `content/scenarios/` following the schema:
```json
{
"id": "my_scenario",
"title": "Der deutsche Titel",
"description": "Short English description of the situation",
"learner_role": "Description in German of who the learner is",
"agent_role": "Description in German of who Sprechi plays",
"information_gap": "What the learner doesn't know that Sprechi does โ this is what drives the scenario forward",
"pre_task_vocab": [
"der Artikel (article)",
"das Wort (word)"
],
"success_criteria": [
"Learner does X",
"Learner correctly uses Y"
],
"grammar_opportunities": [
"Pattern: Ich mรถchte einen...",
"Structure: weil-clause"
]
}
```
**Rules for scenarios**:
- `pre_task_vocab` items must include the article for all nouns โ this
reinforces P4 from the data layer
- 8-12 vocabulary items is the sweet spot
- 4-6 success criteria
- 2-4 grammar opportunities
- The `information_gap` is what makes it a *task-based* scenario, not
just free chat โ there needs to be something the learner has to
discover or figure out
Once the file exists, set `current_scenario` in the profile to match
the new `id`.
### Add a new learner profile (for a second user)
1. Copy `content/profiles/jae.json` to `content/profiles/partner.json`
2. Edit the new file โ change `user_id`, `display_name`, `cefr_level`,
`recurring_errors`, `interests`, etc.
3. Either:
- Change the plugin's `activeProfile` config to `"partner"` to switch
entirely, OR
- (Future: Block 3) Bind the partner's own Discord channel to a second
agent that uses the partner profile
### Edit Sprechi's teaching persona
Two files control Sprechi's persona:
**`~/.openclaw/workspace-sprechi/SOUL.md`** โ core identity and teaching
philosophy. Loaded by OpenClaw automatically into the system prompt.
Keep this focused on *who Sprechi is*.
**`content/persona.md`** โ the 11 detailed pedagogical principles
(P1-P11). Injected by the plugin every turn. Keep this focused on
*how Sprechi teaches*.
The distinction is roughly:
- SOUL.md = identity, warmth, Discord formatting rules, session structure
- persona.md = the full teaching methodology with numbered principles
If you want Sprechi to behave differently (e.g. more or less strict
about corrections, different session pacing), edit `content/persona.md`.
### Edit CEFR level constraints
`content/levels/A1.md`, `A2.md`, and `B1.md` define what grammar and
vocabulary Sprechi may use at each level. Each doc has four sections:
- **Grammar you may use**: tenses, clause types, cases, verb types
- **Grammar you must avoid in your own output**: explicit no-go list
- **Vocabulary**: word family count, introduction rate
- **Sentence complexity**: max length, clause rules
- **Correction focus at this level**: what to prioritize catching
If Sprechi is using structures that are too complex or too simple,
edit the corresponding level file.
---
## Monitoring & debugging
### Check if the gateway is running
```bash
systemctl --user status openclaw-gateway.service
```
### Watch the logs
```bash
journalctl --user -u openclaw-gateway.service -f
```
### See config health
```bash
cat ~/.openclaw/logs/config-health.json | python3 -m json.tool
```
### See the full per-turn log
```bash
tail -100 /tmp/openclaw/openclaw-$(date +%Y-%m-%d).log
```
### When to restart the gateway
You need to restart after:
- Editing `openclaw.json` (agent, bindings, or plugin config changes)
- Editing any plugin source code (`.ts` files)
- Adding or removing plugin files
You do **NOT** need to restart after:
- Editing profile JSON files
- Ed
... (truncated)
tools
Comments
Sign in to leave a comment