Skip to main content

INVOKE MODELS FROM MODELS

This guide shows you how to use context.runModel() to invoke one model's method from inside another model's execute function.

Declare the dependency

Your extension's manifest must list the target model's extension in dependencies. Without this declaration, runModel rejects the call at runtime.

# manifest.yaml
name: "@mycollective/orchestrator"
version: "2026.07.10.1"
dependencies:
  - "@mycollective/worker-model"
models:
  - orchestrator.ts

Invoke by definition name

If the target model already has a definition in the repository, pass the definition name:

const result = await context.runModel("my-worker", "process", {
  input: "some-value",
});

if (result.ok) {
  context.logger.info(`Worker produced ${result.resources.length} resource(s)`);
} else {
  context.logger.error(`Worker failed: ${result.error}`);
}

Invoke by model type

If no definition exists, pass a model type. Swamp auto-creates a definition in .swamp/auto-definitions/:

const result = await context.runModel(
  "@mycollective/worker-model",
  "execute",
  { region: "us-east-1" },
);

Handle the result

runModel returns a discriminated union. Always check result.ok before accessing result.resources:

const result = await context.runModel("target", "method", args);

if (!result.ok) {
  // result.error contains the failure message
  return { dataHandles: [] };
}

// result.resources is DataHandle[] — references to the target's output
for (const handle of result.resources) {
  const data = await context.readResource(handle.name, handle.version);
  // process the target's output
}

Data ownership

Data written by the invoked model belongs to the target model's definition, not the caller's. The DataHandle references in result.resources point to data under the target's namespace. To use that data in the caller's output, read it via readResource and write a derived resource under the caller's own spec.

Limits

A single top-level method execution enforces:

  • Maximum call depth of 10
  • Maximum 100 total runModel invocations
  • Cycle detection — a model cannot invoke itself, directly or transitively
  • Vault isolation — the invoked model sees only its own extension's vault bindings

Exceeding any limit causes runModel to return { ok: false, error: "..." }.

Remote workers

runModel is not available on remote workers. If your model's method may run on a worker, do not call runModel from it — the call throws an error. Restructure the work so that the model invocation happens on the orchestrator.

Refer to the model reference for the full runModel signature, and Models, Types, and Methods for the design rationale.