Een geïsoleerde, auditbare runtime voor tenant-specifieke AI-workflows
Een Skill is een benoemde, geversiede bundel van prompt + tools + policy die het platform draait in een gehardende sandbox. Vijf kernel-isolatielagen, vier trust tiers, SHA-256 bundle-integriteit en een append-only audit ledger. Deze pagina laat zien hoe het in elkaar zit.
Van formulier tot artifact, vanuit de stoel van de gebruiker
Een trouwe spiegel van de Skill-runner in de workbench. Hetzelfde formulier dat uw team invult, hetzelfde state-badge, dezelfde tool-call-timeline, dezelfde kosten-regel onderaan. Het blok hieronder toont dezelfde uitvoering vanuit de sandbox-zijde.
Genereer deal-shortlist
Lees deal-materiaal, score tegen investeringscriteria, geef een Excel-samenvatting terug.
Bestanden landen in inputs/materials/ — de skill leest ze via workspace.fs.list.
Optionele natural-language-filter tijdens scoring.
Zie hoe een Skill door de sandbox loopt
Elke aanroep volgt dezelfde preexec-ladder: bundle verify → workspace mount → namespaces + cgroup + UID-drop → seccomp load → exec → tools → artifact commit → archive. Drie scenario's, elk met een ander sandbox-profiel.
Een workflow die uw team bezit, ingepakt
Neem een workflow die uw team blijft herhalen — een contract reviewen, een deal scoren, een briefing voorbereiden — en pak hem in als één benoemde bundel. Die bundel zegt wat hij doet, welke tools hij mag aanraken, welke guardrails gelden en welke vorm zijn output heeft. Mensen roepen hem bij naam aan vanuit de workbench. Agents roepen dezelfde aan vanuit een chat-loop. Zelfde call, zelfde audit trail.
Een contract, geen prompt
Skills zijn geversioneerd en gesigneerd. Dezelfde v1.4.0 vandaag is dezelfde v1.4.0 over een kwartaal — geen kopieer-plak-drift, geen stille aanpassingen, geen verrassingen voor de aanroeper.
Het platform draait hem, niet de aanroeper
Autorisatie, isolatie, kostentoerekening, audit trail — allemaal afgedwongen door de runtime. Identiek voor een mens in de workbench en een agent in een chat-loop.
Komt met zijn eigen paper trail
Elke aanroep levert een getraceerde, gekostende, gearchiveerde run op. Een admin kan elke uitvoering end-to-end bekijken — vandaag, vorige week, vorig kwartaal.
Een LLM in een loop in de sandbox, end to end
Inputs klaargezet
Bestanden gevalideerd tegen het manifest. Workspace gemount, geïsoleerd, gescoped op uw tenant. Sandbox-profiel actief vóór er één regel code draait.
LLM kiest een tool, runtime draait hem, LLM leest het resultaat
Elke stap wordt gecheckt tegen de allow-list, uitgevoerd binnen de sandbox en gelogd. De loop stopt zodra het model output produceert die past in het schema — meestal 3–8 stappen.
Output + artifacts
Gestructureerde output gaat terug naar de aanroeper. Bestanden worden downloadbare artifacts. Kosten- en trace-rijen geschreven. De workspace gaat het archief in.
↓De rest van deze pagina is hoe het platform dat afdwingt — laag voor laag.
Drie lagen bewaken elke aanroep
Procesisolatie, trust-classificatie en bundle-integriteit stapelen onafhankelijk. Eén ervan kan fail-closed gaan zonder de andere mee te trekken.
Procesisolatie
Elke run krijgt een verse, afgeschermde procesomgeving. Vóór er code draait, bepaalt het platform wat de Skill mag zien op disk, of hij een netwerk heeft, hoeveel geheugen en CPU hij krijgt en welke low-level operaties hij mag aanroepen.
Trust-classificatie
Elke Skill-versie draagt één van vier tiers — official, verified, community of tenant. Admins zien de tier in de catalog, zetten per-space-beleid op welke tiers mogen draaien en geven goedkeuring vóór tenant-gebouwde Skills live gaan.
Tamper-detectie
Elke versie heeft een fingerprint die bij publish wordt berekend. Vlak vóór elke run rekent het platform die opnieuw uit en vergelijkt. Mismatch — al is het maar één byte — en de run wordt geweigerd vóór er code draait.
Vijf dingen die het besturingssysteem zelf afdwingt
Elke laag beantwoordt een andere vraag: wat kan de Skill zien, waar kan hij bij, hoeveel mag hij gebruiken, wat mag hij aanroepen, hoe luid mag hij zijn? In vaste volgorde — als er één laag mislukt, start de Skill helemaal niet.
Het bestandssysteem, afgeschermd
De Skill ziet alleen zijn eigen workspace-folder. De host-schijf, bestanden van andere tenants, alles buiten zijn boom — onzichtbaar. Mount hij iets nieuws, dan kan die mount niet terug lekken naar de host.
kernel ·CLONE_NEWNS · MS_SLAVENetwerktoegang, aan of uit — bij de kernel
Skills geven in hun manifest aan of ze het netwerk nodig hebben. Is het antwoord nee, dan heeft de draaiende Skill letterlijk geen netwerkinterface — niet 'we vergaten er één te maken', maar 'de kernel heeft er geen om uit te delen'. Vanuit Python is daar geen omweg omheen.
kernel ·CLONE_NEWNETGeheugen en CPU, hard begrensd
Elke run krijgt een plafond — 512 MB geheugen, 60 CPU-seconden. Gaat een Skill erover, dan kapt het besturingssysteem hem af en leggen we precies dat vast. Andere tenants merken het niet, geen druk lekt door naar de host.
kernel ·cgroup v2Een allow-list van low-level operaties
Bovenop de Python-sandbox laat de kernel zelf de Skill alleen een vaste lijst low-level operaties uitvoeren. Rauwe sockets, kernel-module-trucs, exotische IPC — geweigerd door de kernel, niet door onze code. Skills krijgen wat ze nodig hebben en niet meer.
kernel ·seccomp BPFLogs die het systeem niet kunnen verzuipen
Elke run vangt de eerste 10 MiB van zijn eigen logs op, markeert de rest als afgekapt en gaat door. Operationeel, geen security: het voorkomt dat een lawaaiige Skill de runtime blokkeert of opslag volpropt.
kernel ·10 MiB capHarde plafonds op elke uitvoering
Identieke defaults ongeacht caller, tier of space. Tenants kunnen ze in policy verlagen, niet boven het platform-cap brengen.
Eén interface, drie execution-backends
Het CodeExecAdapter-protocol laat de runtime van execution-backend wisselen zonder dat de Skill of de aanroepende code verandert. Tier 1 is vandaag live; tier 2 en 3 zitten achter dezelfde interface en volgen op hetzelfde trust-model.
subprocess-v1
OS-niveau hardening op de runtime-host. De vijf preexec-lagen hierboven. Vandaag de default voor elke uitvoering; productieklaar, fail-closed, geïnstrumenteerd.
gVisor / Firecracker
User-space kernel of microVM-isolatie voor zwaardere workloads. Zelfde adapter-contract; registreert onder andere naam. Gericht op hoger-risico tenant-skills.
Remote execution
Off-host execution in e2b of Modal voor elastische capaciteit en strakkere fysieke scheiding. Hetzelfde protocol, asynchroon worker-pool — geen API-wijziging voor aanroepers.
Vier tiers, één runtime
Tiers staan op elke Skill-versie en zijn zichtbaar in de workbench (badges) en in de console (filters en policy-panels). Voor elke tier draait dezelfde isolatie; de tier bepaalt wie de Skill mag schrijven en waar hij mag draaien.
Official
Door Aimable geleverde platform-skills. Intern reviewed en getekend. Zichtbaar voor elke tenant tenzij een admin ze verbergt.
Verified
Door derden geschreven, door Aimable gevalideerd. Gecureerd en gereviewed vóór publicatie; veilige defaults voor cross-tenant gebruik.
Community
Public-marketplace skills. Draaien in dezelfde sandbox als alles, maar admins beslissen per space of community-tiers überhaupt zijn toegestaan.
Tenant
Privé-skills geschreven binnen één tenant. Nooit zichtbaar buiten die tenant. Forward-deployed engineers leveren de meeste daarvan vandaag.
De versie die u goedkeurde is de versie die draait
Wanneer een Skill-versie wordt gepubliceerd, berekent het platform een fingerprint over de hele bundle — prompt, playbook, resources, scripts — en bewaart die naast de versie. Vlak vóór elke run wordt diezelfde fingerprint opnieuw berekend en vergeleken. Eén byte verschil ergens — een stille edit, een vervanging in storage, wat dan ook — en de run wordt geweigerd vóór er code draait. De v1.4.0 waar uw reviewer ja op zei, is bit-voor-bit dezelfde v1.4.0 die morgen in productie draait.
Een nieuwe versie komt in de catalog als één bevroren bundle. Het platform berekent op datzelfde moment de fingerprint. De bundle zelf kan nooit ter plaatse worden bewerkt — een wijziging is een nieuwe versie-rij, met een nieuwe fingerprint.
De fingerprint reist met de versie mee als een serienummer. Admins zien hem in de console; auditors vergelijken er later tegen. Zelfde versie, zelfde fingerprint, waar de Skill ook gaat.
Vlak vóór uitvoering rekent het platform de fingerprint opnieuw uit en vergelijkt. Match: de Skill draait. Mismatch: geweigerd, vastgelegd in audit, geen code draait — geen ontsnappingsroute.
Eenmalig per-execution filesystem
Workspaces zijn tenant-scoped, gekeyed op (tenant_id, execution_id) en worden afgebroken bij voltooiing. De boom op disk leeft nooit langer dan de uitvoering; alleen de gearchiveerde tar.gz, en alleen voor een begrensde retentie.
Default archief-retentie is 7 dagen. Een cleanup-job verwijdert de tar.gz en zet deleted_at; de rij blijft voor audit.
/workspace/{tenant_id}/{execution_id}/
├── inputs/ # bundle, ro
│ └── bundle/ # skill payload
├── scratch/ # rw, ephemeral
├── outputs/ # rw, promoted to artifacts
└── metadata.json # execution metadata- Elke uitvoering krijgt een UID uit een vooraf aangemaakte pool (
aimable-skill-0…63) zodat UID-botsingen tussen executions in een pod niet voorkomen. - Elk workspace-pad is voorvoegselt met
tenant_id; cross-tenant-requests gevencross_tenant_access_error. - Artifact-commits zijn append-only — een nieuwe commit op hetzelfde pad geeft een nieuwe rij, nooit een in-place overschrijving.
Drie paden komen samen in één intersection-gate
Een Skill mag een tool niet aanroepen omdat hij er om vraagt. Drie onafhankelijke declaraties worden bij runtime ge-intersect — het resultaat is de enige set die de LLM ooit ziet.
manifest.allowed_toolsSkill-manifest declaratie
De Skill-auteur somt in het manifest tools op die de Skill nodig heeft. Dat is intentie, geen autorisatie — op zichzelf geeft het niets.
space.enabled_toolsSpace-policy
Een space-admin schakelt tools per space in. Gegeerd door RBAC (spaces.write). Dit is de operator-view.
compose_execution_tools()Runtime intersection-gate
compose_execution_tools() neemt de doorsnede, strijkt netwerk-tools weg bij sandbox.network=deny en voegt platform-meta-tools toe.
selected = (manifest.allowed_tools ∩ space.enabled_tools)
− tools_requiring_network if sandbox.network = "deny"
+ meta_tools(skill.describe, skill.invoke, artifact.commit)Onbekende tool-namen uit het manifest worden bij compositie stilzwijgend gedropt. Roept de LLM er toch een aan, dan ziet hij unknown_tool_reference als resultaat — de runtime praat met het model, niet met de gebruiker.
SKILL.md is het contract
Hetzelfde manifest dat de workbench rendert, de runtime parseert en de console tussen versies diffed. Hieronder: een echte review-contract Skill, links het manifest, rechts een live aanroep.
Lees een SaaS-contract, markeer clausules tegen het huis-playbook en geef een review-memo terug met risico's en redline-suggesties.
- filecontract PDF of DOCX, ≤ 25 MB
- collectionplaybook Huis-playbook, scoped op space
- sandbox.network = deny (geen externe retrieval)
- sandbox.code_exec = false (geen Python-tool)
- PII in outputs geredigeerd (presidio)
- EU data residency afgedwongen upstream
{ memo: markdown, clauses[], risks[], score: number }Eén gedeelde venv, bewust
Skills draaien tegen dezelfde /app/.venv als de Aimable-backend — zo'n vijftig gecureerde packages, waaronder numpy, pandas, torch, transformers, spacy, docling, openpyxl, httpx, sqlalchemy, langfuse, cryptography en litellm.
Er is geen pip install tijdens uitvoering. Bewuste trade-off: het sluit supply-chain-hijack tijdens een run uit, maar Skills kunnen geen eigen versies pinnen.
Terwijl het platform rijpt, schrijven onze forward-deployed engineers de Skills met u mee. Per-skill venvs met SHA-pinned wheels zijn de volgende stap (AIM-685) — tot dan begrenzen de kernel-lagen wat een misdragende library kan aanrichten.
Selectie pre-installed packages
Wat in de venv zit, is bereikbaar vanuit een Skill-proces. UID-drop, seccomp en netns beperken wat dat kan opleveren — maar een kwetsbare library vergroot wel de blast radius. De wheels-pattern op de roadmap dicht dat gat.
Wat een Skill wel en niet kan
Expliciet uitgeschreven. Een bruikbaar threat model is er één waarover u kunt redeneren — vage beloftes van 'enterprise-grade isolation' kopen gereguleerde klanten niet.
- Bestanden in inputs/ lezen (bundle-resources en door de aanroeper aangeleverd materiaal)
- Schrijven naar scratch/ en outputs/ (read-only inputs/ afgedwongen door mount)
- Python uitvoeren via workspace.code.python wanneer sandbox.code_exec=true
- Libraries aanroepen die al in /app/.venv staan (numpy, pandas, openpyxl, litellm, …)
- Externe URLs bereiken alleen wanneer sandbox.network=allow én een netwerk-tool is goedgekeurd
- Het host-filesystem buiten zijn workspace-boom raken (mount-ns + path-validator)
- Een andere tenant of space zien — elk pad en elke service-call is tenant-scoped
- Een privileged proces starten (setuid drop naar low-priv UID vóór execve)
- Syscalls doen buiten de seccomp-allowlist (kernel geeft EPERM)
- Geheugen of CPU uitputten (cgroup v2 hard caps; OOM-kill vastgelegd)
- Voorbij het wall-clock budget draaien (tree-killed via session-leader bij timeout)
- Exfiltreren over het netwerk bij sandbox.network=deny (geen interfaces in de netns)
Tenant-grenzen zijn filesystem-diep
Skills, workspaces, artifacts en audit-rijen zijn allemaal gekeyed op tenant_id. De workspace-boom, de UID-toewijzing en elke service-call dwingen het onafhankelijk af.
tenant_id; de path-validator weigert traversal terug omhoog.aimable-skill-0…63) — geen gedeelde UID tussen executions.tenant_id; mismatches geven cross_tenant_access_error bij de API.Elke uitvoering is observable en attribueerbaar
Vier parallelle signalen landen voor elke Skill-run. Samen beantwoorden ze 'wat is er gebeurd, wie heeft het betaald en wat heeft het aangeraakt?'.
Append-only event-ledger
skill_execution_event vangt execution_started, state_changed, content_delta, tool_call_start/end, artifact_committed, execution_completed. Resumable; voorbij retentie gepruned.
Langfuse-trace per execution
Root span draagt tenant_id, space_id, principal_id, skill_slug, skill_version, execution_id, parent_execution_id, source. Tool-calls en sub-skills nesten als child-spans.
Prometheus-metrics
skills_execution_active_count, skills_execution_duration_ms, skills_execution_result_total en skills_tool_invocation_total — alerts hangen aan bestaande infra.
Kosten-attributie
Elke llm.complete-call schrijft een USAGE_EVENT met model, input/output-tokens en cost_usd. Per skill, space en principal opgerold in de console-audit-pagina.
Tickets waar we eerlijk over zijn
Vier MC5-getagde items staan nog op de werklijst. We benoemen ze zodat u weet wat vandaag wel en niet in productie zit.
pivot_root voor volledige filesystem-confinement
Mount-ns + MS_SLAVE voorkomt vandaag dat host-mounts propageren, maar /proc, /sys en /dev zijn nog zichtbaar. pivot_root in de workspace-boom plus tmpfs voor /proc en een minimale /dev sluit dat gat.
Trust-tier handhaving op runtime
Tiers worden vandaag vastgelegd en getoond. Per-space admin-policy, goedkeuringsflows en een per-space tier-filter moeten nog landen. De console-UI bestaat; het backend-endpoint nog niet.
Spec / code-afstemming op FR-005
Sluit de intersection-gate-beslissing definitief: vandaag staat hij in tool_composition.py en matcht de spec; dit ticket formaliseert de testdekking zodat spec en code synchroon blijven.
Wheels-pattern voor per-skill dependencies
Vervang de single shared venv door per-skill dependency-declaraties + SHA-pinned wheels die bij bundle-time worden ingepakt. Dicht het supply-chain-bereik dat een Skill nu in Aimables interne dependencies heeft.
Vroege toegang voor design partners
We schrijven de eerste set Skills mee met technische leads die een gereguleerde workflow eigen hebben. Heeft u zo'n workflow — en wilt u de kernel-niveau isolatie er onder — dan praten we graag.
Draai AI in een sandbox waarover u kunt redeneren.
Boek een demo of vertel ons welke workflow uw team blijft herhalen. We verpakken de eerste Skill samen met u en lopen de complete audit trail door.
