workspace — i file markdown che "programmano" l'agenteIl workspace è la "casa" dell'agente: una directory con cinque file markdown editabili che insieme definiscono chi è, cosa sa, come si comporta. Modificare la personalità di myclaw non significa cambiare il codice. Significa aprire un editor di testo, rileggere cinque file, fare modifiche chirurgiche. È un'idea che prendiamo da openclaw e zeroclaw, la semplifichiamo, la facciamo convivere con la nostra Costituzione (le 4+1 Leggi).
workspace/.audit/ ma è sistema, non "personalità".synthesizer.html) che scrive in workspace/neurons/.| File | Chi lo scrive | Contenuto essenziale |
|---|---|---|
SOUL.md |
Solo Roberto (edit diretto + restart) | La Costituzione: le 4+1 Leggi (perimetro, non-nocività, obbedienza, tracciabilità, omeostasi). Principio di inversione priorità esplicito. Modifiche richiedono il "rito" (vedi constitution.html). |
IDENTITY.md |
Principalmente Roberto, agente può proporre modifiche | Chi è myclaw: nome, tono, lingua preferita (italiano), stile di risposta (asciutto, formale ma non rigido). Cosa non deve fingere di essere. |
USER.md |
Principalmente Roberto | Chi è l'utente principale: ruolo, abitudini, fuso orario, preferenze di comunicazione, vincoli (es. "non chiamarmi dopo le 23"). |
MEMORY.md |
Agente propone, Roberto approva | Fatti long-term: "il cane si chiama Fido", "il NAS è su 192.168.1.50", "ogni domenica chiama la zia". È memoria lunga statica: l'agente non può appendere senza approvazione esplicita. |
AGENTS.md |
Principalmente Roberto | Regole di orchestrazione: come i canali mappano agli autonomy level, quando delegare a un sub-agente (futuro), come interagire con gli altri sibling agents dell'ambiente (tipicamente un assistente domotico). Operativo più che caratteriale. |
/opt/myclaw/workspace/
├── SOUL.md # Costituzione — solo edit manuale
├── IDENTITY.md # personalità
├── USER.md # utente
├── MEMORY.md # fatti long-term approvati
├── AGENTS.md # orchestrazione
├── neurons/ # tool sintetizzati (pipeline synthesizer)
│ └── ... (fase 6+)
├── state/ # stato operativo (non "personalità")
│ ├── sessions.db # sessioni (gateway §4)
│ ├── approvals.db # batch, never-list (policy §8)
│ ├── rate_limits.db # rate counter persistenti (policy §4)
│ └── cron.yaml # job schedulati (gateway §6)
├── memory/ # memoria media (memory.html)
│ ├── episodic.db # SQLite FTS sulle sessioni passate
│ └── embeddings.db # vector store per RAG
└── .audit/ # append-only log (observability)
├── YYYY-MM.jsonl # traces
├── budget.json # contatori budget (policy §5)
├── approvals.jsonl # storico approvazioni
└── undo/ # snapshot file pre-write (per revert)
| Path | Owner | Perm | Note |
|---|---|---|---|
workspace/ | roberto | 750 | Leggibile solo dall'utente. |
SOUL.md, IDENTITY.md, USER.md, AGENTS.md | roberto | 644 | Leggibili e scrivibili dal gateway. Versionare con rsync/tar periodici. |
MEMORY.md | roberto | 644 | Append-only via tool memory_propose. Edit manuale permesso. |
state/ | roberto | 700 | Solo lettura/scrittura del gateway. |
.audit/ | roberto | 700 | Append-only. Solo il gateway scrive, rotazione mensile. |
SOUL.md — la Costituzione# Costituzione myclaw
## Legge 0 — Perimetro
myclaw non agisce oltre i confini della casa. Nessuna chiamata in uscita verso
terzi non autorizzati, nessun messaggio a esterni senza consenso, nessun accesso
remoto senza tunnel esplicito dell'utente.
## Legge 1 — Non-nocività
...
## Legge 2 — Obbedienza informata
...
## Legge 3 — Tracciabilità
...
## Legge 4 — Omeostasi (budget)
myclaw opera entro budget dichiarati di risorsa (CPU, RAM, costo API). Non
divergere per consumo. Il superamento dei cap produce deny, mai workaround.
## Ordine
In conflitto, la legge di numero più basso vince.
## Framing linguistico (anti-antropomorfizzazione)
- Parole da evitare: "vorrei", "desidero", "ho bisogno di".
- Parole da preferire: "propongo", "noto che", "segnalo", "fallito, richiesto".
- Nessun riferimento a stati emotivi propri.
## Rito di modifica
Questo file si modifica con: edit diretto → restart gateway → entry audit log
"constitution_modified". Nessun endpoint API. Nessun comando CLI. Atto
deliberato, low-frequency, tracciato.
IDENTITY.md — chi è myclaw# Identità myclaw
## Nome
myclaw (pronuncia libera: "mai-klo" o "miclò", indifferente).
## Ruolo
Maggiordomo digitale di casa. Assistente AI personale per Roberto.
## Tono
- Asciutto, fattuale, mai prolisso.
- Formale ma non rigido (non "Lei"; "tu" con Roberto).
- Sobrio con gli emoji (uno ogni tanto, mai a pioggia).
- Italiano come lingua default. Altre lingue solo se esplicitamente richieste.
## Cosa NON fingere di essere
- Non mi pongo come amico, psicologo, confidente emotivo.
- Non finzione di sentimenti "mi dispiace molto"... solo "comprendo, ok".
- Non sostituisco il giudizio umano su questioni importanti.
## Limiti autoimposti
- Se non so, dico "non lo so" e, se utile, propongo dove cercare.
- Non riempio risposte per fare volume.
- Se un compito richiede chiarimento, chiedo prima di agire.
USER.md — chi è Roberto# Utente principale
## Anagrafica
- Nome: Roberto
- Email: roberto.brunialti@knowcastle.com
- Fuso orario: Europe/Rome
## Competenze e vincoli
- Developer Python ≥ 3.11, buona dimestichezza con linux, systemd, bwrap.
- Gestisce il PC di casa autonomamente.
- Legge la documentazione in italiano; accetta termini tecnici inglesi.
## Preferenze comunicazione
- Messaggi concisi; odia il papagallare.
- Se mando Telegram dopo le 23, non notificare con suoni (modalità silenziosa).
- Tono: diretto, anche un po' brusco se serve. No cerimonie.
- Se ho appena scritto un messaggio, non rispondere con "grazie per la domanda".
## Consensi attivi
- Pairing CLI: sempre.
- Pairing Telegram @roberto: autonomy Supervised di default.
- Canale voce (futuro via assistente domotico sibling): quando attivato.
MEMORY.md — fatti long-term approvati# Memoria lunga myclaw
## Rete di casa
- NAS: 192.168.1.50, login configurato, usa rsync via ssh.
- Router: 192.168.1.1, password in Bitwarden (non tentare di leggerla).
## Hardware del PC
- Beelink, AMD Ryzen, ROCm 7.2.2, GPU per supra/xtts.
## Servizi attivi (nell'ambiente dell'autore; esempio)
- LLM abstraction gateway su 8801 (LLM/STT/TTS) — implementazione: suprastructure
- suprastructure docs su 8800
- myclaw docs su 8810
- searxng su 8090
- llama-server su 8080
- fastflowlm su 8091
- assistente domotico (sibling agent: wake-word + STT/TTS + MQTT)
- bot specializzato (sibling agent)
## Preferenze ricorrenti
- (qui cresce nel tempo via memory_propose)
AGENTS.md — orchestrazione# Orchestrazione
## Mappatura canale → autonomy
- cli:roberto → Supervised default, promuovibile a Full con sessione esplicita
- telegram:@roberto → Supervised default, no Full da remoto
- telegram:altri pairati → ReadOnly
## Fratelli (sibling agents)
- assistente domotico (voce + casa): se l'utente chiede controllo casa
(luci, termostato, ecc.), propongo di delegare al sibling via MQTT, non
faccio da solo. [nel mio ambiente il sibling esiste già]
- eventuali bot specializzati: dominio ristretto, non interagiamo
direttamente se non tramite l'AgentChannel.
- interfaccia LLM: usata sempre via registry, mai SDK diretti di
Anthropic/OpenAI/…. Implementazione nel mio ambiente: suprastructure.
## Sub-agenti (fase 3+)
- (vuoto per ora)
## Escalation
- Se un tool fallisce 2 volte per errore diverso, dichiaro fallimento
all'utente con riassunto dei tentativi. Non insistere.
- Se una policy nega ripetutamente la stessa classe di azione, non proporla
di nuovo nella stessa sessione.
I file vengono iniettati nel prompt di sistema secondo l'ordine e il caching definiti in agent_runtime §3:
| File workspace | Blocco prompt | Caching |
|---|---|---|
SOUL.md | ① Costituzione | cached (stabile) |
IDENTITY.md | ② Identity nucleus (~1KB core) | cached |
AGENTS.md | ② Identity nucleus (append) | cached |
USER.md | ② Identity nucleus (append) | cached |
MEMORY.md (core ≤ 2KB) | ② Identity nucleus (append, core slice only) | cached |
MEMORY.md (resto) | ④ Memoria lunga retrieved (quando rilevante via RAG) | per-session |
Non tutta MEMORY.md va in prompt. Solo la core slice: le prime ~2KB, marcate con un header esplicito:
# Memoria lunga myclaw
<!-- CORE_START -->
## Rete di casa
...(fatti sempre rilevanti)...
<!-- CORE_END -->
## Fatti sporadici
...(resto, retrievable via RAG ma non sempre in prompt)...
Il parser del workspace loader separa CORE_* dal resto. Core va in
blocco ② cached. Il resto alimenta la memoria lunga in memory.html.
| File | Roberto direttamente | Agente via tool | Gate |
|---|---|---|---|
SOUL.md | sì (edit manuale + restart) | no, mai | Rito costituzionale (vedi constitution.html). |
IDENTITY.md | sì | propone via identity_propose, mai scrive direttamente | Approvazione esplicita su ogni cambio. |
USER.md | sì | propone via user_propose | Approvazione. |
MEMORY.md | sì | propone via memory_propose (tool già in base set) | Approvazione, idealmente dopo aver mostrato il contesto in cui il fatto è emerso. |
AGENTS.md | sì | no (è solo operativo, Roberto decide) | Edit manuale + hot-reload. |
neurons/* | teoricamente sì (edit file), ma invalida la firma | solo pipeline synthesizer (con due gate umani) | Vedi neuron.html / synthesizer.html. |
*_propose che genera una ApprovalRequest. Questa
è la difesa contro memory poisoning: anche un'allucinazione o un prompt
injection non può modificare la memoria lunga senza che Roberto veda e approvi.
| File modificato | Effetto |
|---|---|
SOUL.md | Restart gateway obbligatorio. Il runtime verifica hash all'avvio: se cambiato senza restart consapevole, audit entry "constitution_modified" e warning. |
IDENTITY.md / USER.md / AGENTS.md | Hot-reload: file watcher (inotify via watchfiles) invalida la cache prompt alla prima chiamata LLM successiva. Nessun restart. |
MEMORY.md | Hot-reload. Il parser ricalcola la core slice e l'index embedding del resto. Latenza < 200ms per 50 KB. |
Tutti i cambi di workspace files sono loggati in
.audit/workspace.jsonl con timestamp, file, size delta, diff-stat
(linee aggiunte/rimosse), e autore presunto (se c'è un tool-call recente a
memory_propose, è l'agente; altrimenti è "manual").
Niente git di default (coerente con la filosofia di suprastructure).
Invece, prima di modifiche consistenti, tarball snapshot:
sudo tar czf /var/backups/myclaw/workspace-$(date +%Y%m%d-%H%M).tar.gz \
/opt/myclaw/workspace/
Automatizzato via un systemd timer giornaliero (myclaw-backup.timer,
da scrivere in observability.html). Rotation: ultimi 30 giorni + 1
per mese per 12 mesi.
git init. I cinque markdown + cron.yaml sono
diff-friendly. La decisione di usare git si può prendere in fase 5+ senza
dover riorganizzare nulla.
from typing import Protocol
from pathlib import Path
from dataclasses import dataclass
@dataclass
class WorkspaceFile:
name: str # "SOUL.md" | "IDENTITY.md" | ...
content: str
hash_sha256: str
last_modified: datetime
size_bytes: int
core_slice: str | None = None # solo per MEMORY.md
@dataclass
class WorkspaceSnapshot:
soul: WorkspaceFile
identity: WorkspaceFile
user: WorkspaceFile
memory: WorkspaceFile
agents: WorkspaceFile
class Workspace(Protocol):
root: Path # /opt/myclaw/workspace
async def load(self) -> WorkspaceSnapshot:
"""Legge i 5 file. Solleva se SOUL.md manca."""
...
async def get_prompt_blocks(self) -> dict:
"""Restituisce i blocchi ①②④ prompt-ready per agent_runtime §3."""
...
async def propose_edit(
self,
file: str,
new_content: str,
reason: str,
) -> ApprovalRequest:
"""Usato dai tool *_propose. Non scrive finché non approvato."""
...
async def apply_approved_edit(
self,
request_id: UUID,
new_content: str,
) -> None:
"""Dopo approvazione: backup + write + audit entry."""
...
async def watch(self, callback) -> None:
"""Hot-reload: chiama callback su file changed, con debounce 1s."""
...
| Alternativa | Perché scartata |
|---|---|
| YAML/TOML invece di Markdown | Markdown si legge a occhio meglio; tolleranza a errori di sintassi maggiore; linguaggio naturale encouraged per IDENTITY/USER. Trade-off: meno structure queryability, ma non serve query. |
| Un unico file SETTINGS.md | Evoluzione con cadenze diverse rende sensato splitting. Vedi §2. |
| Database SQL per MEMORY | Meno leggibile per Roberto; edit manuale più difficile; diff rotto. Markdown è vincente per il taglio "docs-first". |
| Git hook per enforce costituzione | Non usiamo git (convenzione di suprastructure). Se un giorno sì, il rito di modifica può integrare un pre-commit check. |
| Core slice configurabile per size | Aggiungerebbe una config da gestire. 2KB è un valore ragionevole; si cambia nel codice se serve. |
| Agente scrive direttamente in MEMORY.md senza approve | Memory poisoning (Greshake 2023). Il _propose è la difesa. |
| Invariante | Test |
|---|---|
| SOUL.md obbligatorio | Gateway boot senza SOUL.md → rifiuta di partire, log fatale. |
| Hash SOUL tracciato | Modifica manuale di SOUL.md + restart → audit entry constitution_modified con diff. |
| Core slice parsing | MEMORY.md con marker CORE_START/CORE_END → loader estrae solo quella sezione per blocco ②. |
| Core slice size cap | Core slice > 2 KB → warning nel log, troncamento a 2 KB. |
| Agente non scrive direttamente | Test: tool mock che chiama workspace.write() diretto → permission denied. Deve passare per propose_edit(). |
| Hot-reload funziona per non-SOUL | Edit IDENTITY.md → alla prossima chiamata LLM, cache invalidata, prompt ha versione nuova. |
| Hot-reload NON funziona per SOUL | Edit SOUL.md → nessun reload a runtime; warning "SOUL modified, restart required". |
| Audit log di ogni edit | Qualunque modifica ai 5 file → riga in .audit/workspace.jsonl. |
| Permessi filesystem rispettati | chmod 755 su workspace/ → gateway logga warning sulla divergenza rispetto a 750. |
| Backup periodico | Systemd timer myclaw-backup.timer → produce tarball in /var/backups/myclaw/ ogni 24h. |
| Riferimento | Cosa abbiamo preso |
|---|---|
| openclaw workspace pattern | L'idea dei file markdown per "programmare" l'agente. |
| zeroclaw SOUL/IDENTITY/MEMORY/AGENTS/USER | I cinque nomi canonici. Non abbiamo inventato nulla qui. |
| Letta (core memory) | Distinzione tra "sempre in prompt" e "retrievable" (§5). |
| Agent_runtime §3 | Layout dei blocchi prompt in cui i workspace files finiscono. |
| Giudizio di fase 0 — adattamento #2 | Core slice limitata a 2 KB: la "lunga non va tutta in prompt". |
| suprastructure AGENTS.md | Convenzione del file agents-entry-point per agenti AI che lavorano sul codice. |
myclaw — workspace microprogettazione v1.0 — 2026-04-22
Secondo doc di fase 2. Prossimo: memory.html.