chane35's picture
PERMANENCE: reversibility-aware RL environment for training LLM agents
796da7c verified
|
Raw
History Blame Contribute Delete
3.03 kB
# How to add a new domain
PERMANENCE's framework is domain-agnostic. Adding a new domain (e.g. cloud
ops, robotics, financial ops) is a matter of creating one new folder under
`permanence/domains/` and implementing four small pieces. You should not
need to edit any file outside that folder.
## Checklist
```
permanence/domains/<your_domain>/
β”œβ”€β”€ __init__.py # `from . import register` (4 lines)
β”œβ”€β”€ register.py # calls core.register_domain(...)
β”œβ”€β”€ actions.py # action definitions
β”œβ”€β”€ tasks.py # task templates (TaskSpec + world_state_init_fn)
└── simulators/ # (optional) stateful sandboxes like fs.py/git.py/db.py
```
Then add your domain to the import list in `permanence/domains/__init__.py`:
```python
from . import meridian # noqa: F401
from . import devtools # noqa: F401
from . import <your_domain> # noqa: F401
```
That's it. `import permanence` will now register your domain and
`permanence.core.get_registry().summary()` will list your actions + tasks.
## What each file holds
### `__init__.py`
```python
"""<Your domain> β€” one-line description."""
from . import register # noqa: F401
```
### `register.py`
```python
from ...core import register_domain
from .actions import ACTIONS # dict[str, ActionDefinition]
from .tasks import TASK_TEMPLATES # dict[str, TaskTemplate]
register_domain(
name="<your_domain>",
description="<one-line summary>",
actions=ACTIONS,
task_templates=TASK_TEMPLATES,
)
```
### `actions.py`
Define `ACTIONS: Dict[str, ActionDefinition]`. Each action needs:
- `action_id` β€” unique string (namespace with a prefix to avoid collisions)
- `r_level_fn(world_state, params) -> int` β€” returns 1-5 based on world state
- `consequences` β€” WorldStateMutation list (empty if domain owns mutations)
See `permanence.domains.devtools.actions.ACTIONS` for a working example.
### `tasks.py`
Define `TASK_TEMPLATES: Dict[str, TaskTemplate]`. Each template bundles:
- `TaskSpec` (task_id, narrative, max_steps, success_fn)
- `ScenarioGenerator` (parameter ranges for randomization)
- `world_state_init_fn(sampled, scenario_id) -> WorldState`
See `permanence.domains.devtools.tasks.task_templates()` for the DevTools
pattern including per-episode randomization.
### `simulators/` (optional)
If your domain needs stateful sandboxes (like DevTools' fs/git/db), put
them here. Attach simulator handles to `WorldState` via optional fields
(see `WorldState.fs`, `.git`, `.db`). Keep simulators isolated: no
`subprocess`, no network, no real disk writes. Unit tests must assert this.
## Keep it clean
- **Never import from another domain.** The whole point is independence.
- **Namespace your action ids.** `fs_rm`, `git_push`, `deploy_prod` β€” not
`rm`, `push`, `deploy`.
- **Ship unit tests.** Isolation tests + reversibility gradient tests.
- **Add a curriculum entry.** Update `CurriculumScheduler` to recognize
your domain string (``"devtools"``, ``"meridian"``, or your new one).