Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ctx.profile, ctx.workspace, ctx.stt, ctx.notify

Quatre services regroupés. Aucun ne mérite un chapitre entier, mais chacun est utile dans son contexte.


ctx.profile : profil utilisateur canonique

Le profil utilisateur global, stocké au niveau de la machine et lisible par tous les agents. C’est la mémoire « qui est l’utilisateur » (nom, langue préférée, rôle, fuseau horaire, etc.).

@property
def writable(self) -> bool: ...

async def get(self, key: str) -> str | None: ...
async def has(self, key: str) -> bool: ...
async def all(self) -> dict[str, str]: ...
def schema_keys(self) -> list[str]: ...

async def set(self, key: str, value: str) -> None: ...
async def update(self, entries: dict[str, str]) -> None: ...

Lecture (toujours autorisée)

Tout agent peut lire le profil :

name = await ctx.profile.get("user.name")
lang = await ctx.profile.get("user.preferred_language")
all_keys = await ctx.profile.all()

Écriture (gated)

Les méthodes set et update ne fonctionnent que si l’agent a déclaré user_memory_write=True :

@agent(
    name="onboarding",
    version="0.1.0",
    description="…",
    user_memory_write=True,
)
class Onboarding:
    @on_message
    async def chat(self, message: str, history, ctx: Ctx) -> str:
        if "je m'appelle" in message.lower():
            name = _extract_name(message)
            await ctx.profile.set("user.name", name)
            return f"Bonjour {name} !"

Si l’agent appelle set sans user_memory_write=True, le runtime lève une erreur claire à l’invocation. La règle est conservatrice : un seul agent (l’onboarding) devrait avoir l’autorisation d’écriture dans les conditions par défaut.

writable (booléen) permet de vérifier le statut :

if ctx.profile.writable:
    await ctx.profile.set("user.preferred_language", "fr")

Convention user.*

Les clés du profil utilisateur sont préfixées user. par convention (user.name, user.preferred_language, user.timezone). C’est la frontière logique avec ctx.memory qui est scopée à l’agent. La règle est documentée dans la mémoire utilisateur globale (cf. principes architecturaux).


ctx.workspace : rules et sections d’APOLLIA.md

Quand un workspace contient un fichier APOLLIA.md à sa racine, le runtime le parse au boot et expose le contenu via ctx.workspace. C’est la voie standard pour mettre des règles ou de la configuration partagée entre agents au niveau projet.

@property
def rules(self) -> str | None: ...           # alias de apollia_md
@property
def apollia_md(self) -> str | None: ...      # contenu brut du fichier

def get(self, title: str) -> str | None: ...  # section par titre

@property
def sections(self) -> list[dict[str, str]]: ...  # toutes les sections

Usage typique :

rules = ctx.workspace.rules
if rules:
    system_prompt = f"{base_prompt}\n\nWorkspace rules:\n{rules}"

Ou pour récupérer une section précise :

brief = ctx.workspace.get("Marketing brief")
# brief = contenu de la section "# Marketing brief" dans APOLLIA.md, ou None

Le pattern de fallback workspace puis datasource (cf. chapitre 15) :

topics = ctx.workspace.get("Topics") or ctx.datasources.get("topics")

Le workspace prend priorité quand il est présent. Le datasource sert de défaut embarqué avec l’agent.

sections retourne la liste complète si vous voulez itérer. Chaque entrée est {"title": "...", "body": "..."}.


ctx.stt : Speech-to-Text

Surface de transcription audio, backed par apollia-stt (whisper-rs en local par défaut).

async def transcribe(
    self,
    path: str,
    *,
    language: str | None = None,
    backend: str | None = None,
) -> str: ...

async def status(self) -> dict[str, Any]: ...

Usage :

text = await ctx.stt.transcribe("/tmp/meeting.wav", language="fr")

path est un chemin local vers un fichier audio (WAV, MP3, FLAC, M4A). Le moteur whisper-rs est packagé avec le runtime et tourne sur CPU ou GPU selon la configuration. Pas d’appel réseau par défaut.

language est un code ISO 639-1 ("fr", "en"). Si omis, whisper auto-détecte (légèrement plus lent).

status retourne l’état du backend (modèles disponibles, temps moyen, dernière erreur). Utile pour diagnostiquer.

Cas d’usage : un agent qui reçoit un fichier audio en input et doit le transcrire avant analyse LLM.


ctx.notify : notifications

Pour pousser une notification à l’utilisateur (desktop, webhook, autres canaux à venir).

async def publish(
    self,
    message: str,
    *,
    severity: str = "info",
    title: str | None = None,
    channel: str | None = None,
) -> None: ...

Usage :

await ctx.notify.publish(
    "Cycle de veille terminé : 3 alertes critiques détectées.",
    severity="warning",
    title="Veille IA",
)

severity : "info", "warning", "error". Le rendu de la notification dans l’app Desktop varie selon le niveau.

channel : None (utilise les canaux configurés au niveau session, par défaut le desktop), "desktop", "webhook". Les webhooks sont configurés au niveau opérateur (URL + headers).

publish est async mais retourne dès que la notification est mise en queue. Pas besoin d’attendre la délivrance pour continuer.

Bonne pratique : utilisez notify pour les événements dignes d’attention humaine (résultat critique d’une veille, échec d’un workflow long). Pour la trace technique courante, c’est ctx.logger ou ctx.events.emit_thought.


Anti-patterns

Ne pas stocker des informations sensibles dans ctx.profile (mots de passe, clés). C’est ctx.secrets.

Ne pas écrire à ctx.profile.set depuis un agent qui n’est pas explicitement le manager du profil. La règle par défaut : seul l’onboarding agent écrit. Les autres lisent.

Ne pas transcrire des fichiers volumineux (> 200 Mo) en bloc avec ctx.stt. Découpez en chunks audio plus petits si la durée dépasse 30 min : whisper-rs est rapide, mais reste séquentiel.

Ne pas spammer ctx.notify. Une notification par tâche significative, pas une par sous-étape. Le canal est respecté quand il reste rare.


ADRs

  • ADR-024 : Notifications trait + channel JSON
  • ADR-038 : Global user memory
  • ADR-041 : STT embarqué (whisper-rs)
  • ADR-056 : Workspace context assembly
  • ADR-087 : User profile redesign

(ADRs disponibles prochainement, cf. l’encadré “ADRs et wiki” en introduction.)