# Modular Components: FPF Agent Stack
Interfaces and boundaries.
## 1. Component map (runtime)
The system is a thin deterministic orchestrator around one small tool-calling model. Keep components separable so you can swap implementations without changing contracts.
| Component | Responsibility | Key inputs/outputs |
| :--- | :--- | :--- |
| **ModelGateway** | Call Ollama with FunctionGemma; enforce response format; handle retries/timeouts. | in: messages + tool schemas; out: model response/tool_calls |
| **SkillRegistry** | Index skills/ folder; parse SKILL.md; expose search + versioning. | in: filesystem; out: skill metadata + paths |
| **SkillLoader** | Load only selected skills into prompt context; expose tool schemas. | in: selected skill IDs; out: tool schema bundle + instructions |
| **GuardEngine** | Evaluate guard predicates (pass\|degrade\|abstain) using evidence carriers. | in: tool request + context; out: GuardDecision + reasons |
| **ToolRunner** | Execute skill scripts/functions; validate args; capture stdout/stderr. | in: tool_call; out: result + evidence links |
| **AgentFSAdapter** | Run ToolRunner inside AgentFS session; provide overlay FS + audit log. | in: host path; out: session DB + diff |
| **StateStore** | Persist run state (memory, indices) inside AgentFS DB. | in/out: KV + tables |
| **Reporter** | Bundle artifacts: diff, audit summary, cucumber reports, trace JSON. | in: run outputs; out: artifact bundle |
## 2. Data contracts
### 2.1 Tool schema (per skill)
Each skill exposes one or more tools with JSON-schema arguments. Validation is mandatory before execution.
```typescript
ToolSpec {
name: string
description: string
input_schema: JSONSchema
output_schema?: JSONSchema
guard?: GuardSpec
}
```
### 2.2 GuardSpec (tri-state gating)
```typescript
GuardSpec {
predicate: string # human-readable
required_evidence: string[] # evidence carrier IDs/queries
failure_mode: "abstain" | "degrade"
}
GuardDecision = "pass" | "degrade" | "abstain"
```
### 2.3 Run trace
```typescript
RunTrace {
run_id: string
started_at: ISO8601
model: "functiongemma:..."
skill_set: {name, version, hash}[]
tool_calls: {tool, args, guard_decision, result_ref}[]
agentfs_session: {db_path, snapshot_id}
outputs: {artifact_paths: string[]}
}
```
## 3. Boundary rules (FPF-style)
- Descriptions and specs live in `docs/` and `bdd/`. They are not the runtime system.
- All cross-boundary reuse must be explicit: skill version pinning; schema IDs; no implicit ‘same tool’ assumptions.
- Carriers (repos, PDFs, DB files) carry the artifacts; they are not the artifact’s meaning.
## 4. Sequence (happy path)
1. User request arrives.
2. SkillRegistry.search -> candidate skills.
3. SkillLoader loads selected skills (instructions + tool schemas).
4. ModelGateway asks FunctionGemma to choose tool + args.
5. GuardEngine evaluates tool’s guard predicate.
6. If pass: ToolRunner executes inside AgentFS session via AgentFSAdapter.
7. Reporter bundles diff + audit summary + run trace.
## 5. Extension points
- Add new skills without changing core runtime (only SkillRegistry indexing rules).
- Add new guards (e.g., capability thresholds, allowlists, rate limits).
- Add training pipeline that converts RunTrace + expected outcomes into fine-tuning examples.