docs/extensions/TOOL_CALLING_AND_LOADING.md
Rama master · réplica de lectura del repositorio original.
# Tool Calling & Lazy Loading
This guide explains how AgentOS wires **extensions (tools)** and **skills (prompt modules)** into a tool-calling agent loop, and what “lazy loading” means in practice.
## Tool Calling Loop (Runtime)
At a high level, each turn looks like:
```mermaid
sequenceDiagram
participant U as User
participant G as GMI
participant P as LLM Provider
participant O as ToolOrchestrator
participant E as ToolExecutor
participant T as Tool
U->>G: user message
G->>O: listAvailableTools(persona,user)
O-->>G: tool schemas (OpenAI-style)
G->>P: completion(prompt + tool schemas)
P-->>G: assistant text and/or tool_calls
alt tool_calls present
G->>O: processToolCall(tool_call)
O->>E: executeTool(request)
E->>T: tool.execute(args, ctx)
T-->>E: ToolExecutionResult
E-->>O: ToolCallResult
O-->>G: ToolCallResult
G->>P: follow-up completion (with tool result messages)
end
P-->>G: final assistant text
```
Key implementation points:
- `ToolOrchestrator.listAvailableTools()` returns the tool schemas the model can call this turn.
- `ToolOrchestrator.processToolCall()` enforces permissions and delegates execution to [`ToolExecutor`](https://github.com/framerslab/agentos/blob/master/src/core/tools/ToolExecutor.ts).
- [`ToolExecutor`](https://github.com/framerslab/agentos/blob/master/src/core/tools/ToolExecutor.ts) resolves tools from the tool [`ExtensionRegistry`](https://github.com/framerslab/agentos/blob/master/src/extensions/ExtensionRegistry.ts) by tool-call name (`ITool.name`).
## Extensions: How Tools Load
AgentOS loads extension packs from `extensionManifest.packs` via `ExtensionManager.loadManifest()` and registers descriptors into kind-specific registries.
```mermaid
graph TD
M[ExtensionManifest] --> EM[ExtensionManager.loadManifest]
EM --> RP[Resolve Pack (factory/package/module)]
RP --> P[ExtensionPack]
P --> D[Descriptors]
D --> R[ExtensionRegistry (by kind)]
R --> TE[ToolExecutor (tool registry)]
TE --> TO[ToolOrchestrator]
```
### Pack Resolution Modes
AgentOS supports three ways to resolve a pack entry:
1. `factory`: inline factory returning an [`ExtensionPack`](https://github.com/framerslab/agentos/blob/master/src/extensions/manifest.ts)
2. `package`: dynamic `import()` of an npm package exporting `createExtensionPack()`
3. `module`: dynamic `import()` of a local module path exporting `createExtensionPack()`
### Descriptor IDs For Tools
Tool calling uses the OpenAI-style tool `name`, which maps to `ITool.name`.
For tool descriptors, keep:
- `descriptor.id === tool.name`
## Secrets & Required Secrets
Descriptors can declare `requiredSecrets`. AgentOS resolves secrets from:
1. explicit `extensionSecrets` (host-provided), plus
2. `packs[].options.secrets` (if provided), plus
3. environment variables mapped via the extension secrets catalog (`extension-secrets.json`)
If a descriptor declares a non-optional secret and it can’t be resolved, it’s skipped.
## Skills: Prompt Modules + Optional Tooling
Skills are prompt modules loaded from `SKILL.md` files. Hosts can inject skills into a system prompt via `SkillRegistry.buildSnapshot()`.
For “lazy” skills, the `@framers/agentos-ext-skills` extension pack gives the model tools (`skills_list`, `skills_read` and the rest) that fetch `SKILL.md` content on demand instead of pre-injecting everything; [`SkillRegistry`](https://github.com/framerslab/agentos/blob/master/src/cognition/skills/SkillRegistry.ts) from `@framers/agentos/cognition/skills` loads the skills and builds the snapshot. Curated skill content ships in `@framers/agentos-skills`.
## What “Lazy Loading” Means Here
AgentOS supports a few different “lazy” patterns:
- Lazy optional dependencies: registry helpers can `tryImport()` optional extension packages and skip those not installed.
- Lazy pack import: `package`/`module` entries are imported when `loadManifest()` runs.
- Lazy tool implementation: a tool’s `execute()` can dynamically `import()` heavy dependencies on first call.
### Schema-On-Demand Tool Schemas (Optional)
Tool calling requires schemas **up front for each round**. The **schema-on-demand pattern** works around that with optional meta tools that load extension packs at runtime.
When enabled, AgentOS registers these meta tools:
- `extensions_list` — list loaded packs + curated catalog (if installed)
- `extensions_enable` — load an extension pack at runtime (side effects, HITL recommended)
- `extensions_status` — show packs loaded in this process
Because the GMI loop calls `ToolOrchestrator.listAvailableTools()` on every iteration, any tools added by `extensions_enable` appear in the **next** LLM call’s tool schemas automatically.
```mermaid
sequenceDiagram
participant U as User
participant G as GMI
participant P as LLM Provider
participant O as ToolOrchestrator
participant EM as ExtensionManager
U->>G: user message
G->>O: listAvailableTools()
O-->>G: meta tool schemas only
G->>P: completion(meta tools)
P-->>G: tool_call extensions_enable(...)
G->>O: processToolCall(extensions_enable)
O-->>EM: loadPackFromPackage/module(...)
EM-->>O: new tool descriptors registered
G->>O: listAvailableTools()
O-->>G: meta tools + newly enabled tool schemas
G->>P: completion(updated tools)
```
#### How To Enable In AgentOS
In [`AgentOSConfig`](https://github.com/framerslab/agentos/blob/master/src/api/AgentOS.ts), set:
```ts
schemaOnDemandTools: {
enabled: true,
// Recommended for production: allow curated names only (no arbitrary package imports).
// Default: true in non-production, false in production.
allowPackages: false,
// Default: false (prefer curated packages).
allowModules: false,
// Default: true. When enabled, `extensions_enable` only loads packs present in
// the installed @framers/agentos-extensions-registry catalog.
officialRegistryOnly: true,
}
```
Then start your agent with a minimal `extensionManifest` (or selectively-loaded packs), and let the model call `extensions_enable` as needed.