fai-manifest-create — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited fai-manifest-create (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The fai-manifest.json is the FAI Protocol's wiring file — it binds agents, instructions, skills, hooks, and guardrails into a single deployable solution play. Without it, primitives are standalone; with it, they auto-wire through shared context.
Every manifest has 6 top-level fields. play, version, context, and primitives are required:
{
"play": "01-enterprise-rag",
"version": "1.0.0",
"context": {
"knowledge": ["R2-RAG-Architecture", "O3-MCP-Tools-Functions"],
"waf": ["security", "reliability", "cost-optimization"],
"scope": "enterprise-rag-qa"
},
"primitives": {
"agents": ["./agent.md"],
"instructions": ["./instructions.md", "../../instructions/python-waf.instructions.md"],
"skills": ["./.github/skills/deploy-enterprise-rag/"],
"hooks": ["../../hooks/fai-secrets-scanner/"],
"workflows": [],
"guardrails": {
"groundedness": 0.95,
"coherence": 0.90,
"relevance": 0.85,
"safety": 0,
"costPerQuery": 0.01
}
},
"infrastructure": {
"bicep": "./infra/main.bicep",
"parameters": "./infra/parameters.json"
},
"toolkit": {
"devkit": "./.github/",
"tunekit": "./config/",
"speckit": "./spec/"
}
}| Field | Format | Constraint |
|---|---|---|
play | NN-kebab-case | Must match ^[0-9]{2}-[a-z0-9-]+$ |
version | semver | ^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9.]+)?$ |
context.knowledge | string array | Min 1 item, must reference valid FROOT module IDs (F1-F4, R1-R3, O1-O6, T1-T3) |
context.waf | enum array | Values: security, reliability, cost-optimization, operational-excellence, performance-efficiency, responsible-ai. Min 1, unique |
context.scope | string | Free-form scenario identifier |
primitives.agents | path array | Relative paths to .agent.md files from play root |
primitives.instructions | path array | Relative paths to .instructions.md files. ../../ for shared repo-level ones |
primitives.skills | path array | Paths to skill folders (not SKILL.md files) |
primitives.hooks | path array | Paths to hook folders containing hooks.json |
guardrails.* | number 0-1 | All thresholds are 0-1 range. safety must be integer 0 |
guardrails.costPerQuery | number ≥0 | Max USD per query. Enforced by WAF Cost pillar |
The play ID is the folder name under solution-plays/. Version starts at 1.0.0:
PLAY_ID="42-custom-solution"
mkdir -p "solution-plays/${PLAY_ID}/spec"Map your play's domain to FROOT modules. Common mappings:
R2-RAG-Architecture, F1-GenAI-FoundationsO2-Agents, R1-PromptsO5-Infra, O4-Azure-AIT1-Fine-Tuning, T3-Production-PatternsEvery play must declare at least 1 WAF pillar. Most production plays need all 6. The FAI Engine loads matching .instructions.md files from instructions/waf-*.instructions.md automatically based on these declarations.
Paths are relative to the play's root folder. Use ../../ to reference shared repo-level primitives:
{
"primitives": {
"agents": ["./agent.md"],
"instructions": [
"./instructions.md",
"../../instructions/python-waf.instructions.md"
],
"skills": ["./.github/skills/deploy-my-play/"],
"hooks": ["../../hooks/fai-secrets-scanner/"]
}
}Guardrails define quality gates the FAI Engine evaluates after every agent response. Failures trigger retry or escalation:
| Threshold | Enterprise | Standard | Experimental |
|---|---|---|---|
groundedness | 0.95 | 0.85 | 0.70 |
coherence | 0.90 | 0.80 | 0.70 |
relevance | 0.85 | 0.75 | 0.60 |
safety | 0 | 0 | 0 |
costPerQuery | 0.01 | 0.05 | 0.10 |
safety is always 0 — zero tolerance for safety violations in all tiers.
The three kits partition play contents by audience:
| Kit | Path | Contains | Audience |
|---|---|---|---|
| DevKit | .github/ | Agents, instructions, prompts, skills, hooks, workflows | Developers building with Copilot |
| TuneKit | config/ | openai.json, guardrails.json, agents.json — tunable AI params | Ops/ML engineers adjusting behavior |
| SpecKit | spec/ | fai-manifest.json, fai-context.json, docs, architecture diagrams | Architects reviewing play design |
{
"infrastructure": {
"bicep": "./infra/main.bicep",
"parameters": "./infra/parameters.json"
}
}Non-Azure plays omit the infrastructure field entirely. Docker/K8s alternatives use docker or kubernetes keys instead.
When the FAI Engine loads a manifest, it:
context.knowledgecontext.waf pillarsprimitives.*, validates each file existsWithout the manifest, an agent is just a markdown file. With it, the agent inherits shared context, WAF enforcement, and quality gates automatically.
fai-manifest.json and plugin.json serve different roles:
fai-manifest.json | plugin.json | |
|---|---|---|
| Scope | Full solution play | Single redistributable package |
| Location | spec/fai-manifest.json | plugins/my-plugin/plugin.json |
| Contains | Context wiring + all primitives + infra + toolkit | Package metadata + entry points |
| Purpose | FAI Engine runtime wiring | Marketplace distribution |
A plugin is extracted from a DevKit — it packages a subset of primitives for reuse across plays.
Run the schema validator against your manifest:
# Validate a single manifest
node scripts/validate-primitives.js --verbose
# Quick JSON syntax check
node -e "JSON.parse(require('fs').readFileSync('solution-plays/42-custom-solution/spec/fai-manifest.json','utf8')); console.log('Valid JSON')"
# Validate play ID format
node -e "const m=require('./solution-plays/42-custom-solution/spec/fai-manifest.json'); if(!/^[0-9]{2}-[a-z0-9-]+$/.test(m.play)) throw 'Invalid play ID: '+m.play; console.log('Play ID OK:', m.play)"
# Check all primitive paths resolve
node -e "
const path=require('path'), fs=require('fs');
const root='solution-plays/42-custom-solution';
const m=require('./'+root+'/spec/fai-manifest.json');
['agents','instructions','skills','hooks'].forEach(k=>{
(m.primitives[k]||[]).forEach(p=>{
const abs=path.resolve(root,p);
if(!fs.existsSync(abs)) console.error('MISSING:',abs);
else console.log('OK:',abs);
});
});
"| Mistake | Fix |
|---|---|
Play ID uses underscores (01_rag) | Use hyphens: 01-enterprise-rag |
Guardrail threshold > 1.0 (e.g., 95) | Use 0-1 range: 0.95 not 95 |
| Skill path points to SKILL.md file | Point to the folder: ./skills/my-skill/ not ./skills/my-skill/SKILL.md |
Missing ../../ for shared primitives | Local: ./agent.md. Shared repo: ../../instructions/python-waf.instructions.md |
Adding operational-excellence as ops-excellence | Use exact enum: operational-excellence |
safety set to 0.0 (float) | Must be integer 0 — schema enforces maximum: 0 |
Omitting context.knowledge | Required field, min 1 FROOT module reference |
| Putting manifest in play root | Goes in spec/fai-manifest.json, not play root |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.