Core API
Every Fractal Cloud SDK exposes the same five moving parts. The names below are the TypeScript SDK's; the Java SDK and the Terraform Provider use the same concepts with language-idiomatic spellings.
| Concept | What it does |
|---|---|
| Fractal | The reusable, governed blueprint an infra team authors. References abstract Components only. |
| Component | A Level-1 capability contract (Storage.ObjectStorage). Carries vendor-neutral parameters. |
| Offer | A Level-3 concrete implementation (Storage.PaaS.AwsS3). Carries vendor knobs. |
| Live System | A dev team's instantiation: one Offer selected per Component, deployed into an Environment. |
| Client | Holds credentials once and groups operations by entity (blueprints, liveSystems, environments). |
See Concepts for the full model and Component Reference for the raw catalogue as the agents see it.
Authoring a Fractal
A Fractal declares its blueprint (which Components exist, how they relate) and, optionally, its interface — a set of named operations that are the only permitted way for a consuming dev team to specialize it.
import {createFractal, ObjectStorage, Workload} from '@fractal_cloud/sdk/model';
export const fractal = createFractal({
id: 'acme-api',
version: {major: 1, minor: 0, patch: 0},
boundedContextId: {ownerType: 'Organization', ownerId: ORG_ID, name: 'acme'},
description: 'ACME public API',
blueprint: bp => {
const uploads = bp.add(
ObjectStorage({id: 'uploads'}).withEncryption('at-rest').withPublicAccess(false),
);
const api = bp.add(Workload({id: 'api'}).withPort(8080).withReplicas(2));
bp.link(api, uploads, {access: 'read-write'});
return {uploads, api};
},
operations: (slots, ctx) => ({
withImage: (image: string) => slots.api.set('image', image),
}),
});
createFractal definition
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Fractal name. Combined with version into the fractal id name:major.minor.patch. |
version | {major, minor, patch} | yes | Semantic version of this blueprint revision. |
boundedContextId | OwnerRef | yes | Owning Bounded Context — ownerType, ownerId, name. |
description | string | no | Human description. Defaults to a generated string. |
blueprint | (bp) => Slots | yes | Declares components and links; returns the named slots. |
operations | (slots, ctx) => Ops | no | The Fractal interface — the only customization a consumer may perform. |
The bp handle (blueprint author)
| Method | Description |
|---|---|
bp.add(node) | Register a component in the blueprint and return it. |
bp.link(source, target, settings?) | Declare a runtime link. Blueprint owns all links — see Links. |
The slots / ctx handles (operation author)
| Method | Description |
|---|---|
slots.<name>.id | The component id this handle drives (usable as a link endpoint). |
slots.<name>.set(key, value) | Set a dev-open parameter. Throws if the key is a locked guardrail. |
slots.<name>.append(key, value) | Append to a dev-open list parameter. |
slots.<name>.addChild(node) | Add a child component under this one (e.g. a database under a DBMS). |
ctx.link(source, target, settings?) | Declare a link from inside an operation. |
Guardrails vs dev-open parameters
Every .withXxx() setter on a Component records a parameter and locks it. A locked
parameter is the architect's decision and cannot be changed by a consuming dev team:
ObjectStorage({id: 'uploads'}).withPublicAccess(false); // locked forever
Attempting to override one throws:
Parameter 'publicAccess' on 'uploads' is a locked guardrail and cannot be changed.
Parameters set only through an operation (slots.x.set(...)) are dev-open — the consuming
team decides them. This is the mechanism behind
parameter scopes.
Specializing and building a Live System
import {AwsS3, EcsService} from '@fractal_cloud/sdk/model';
const liveSystem = fractal
.specialize()
.withImage('ghcr.io/acme/api:1.4.2') // an operation from the Fractal interface
.toLiveSystem({
name: 'acme-api-prod',
environment: management.operational('prod').ref(),
select: {
uploads: AwsS3({}),
api: EcsService({launchType: 'FARGATE'}),
},
});
toLiveSystem arguments
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Live System name. |
environment | OwnerRef | yes | Target environment reference — management.ref() or management.operational(name).ref(). |
select | Record<componentId, Offer> | yes | One Offer per top-level blueprint component. |
select is type-checked against the blueprint: an unknown component id, a missing component, or
an Offer that does not satisfy that component's contract is a compile error, and an unknown key is
rejected at runtime too. Child components are not selected — they are emitted by their
parent's Offer in the parent's vendor family (select AzurePostgresDbms and its databases become
AzurePostgresDatabase).
Fractals may also be instantiated without specializing: fractal.toLiveSystem({...}).
Publishing and deploying
Blueprints and Live Systems are separate entities. Deploying a Live System never publishes a blueprint as a side effect.
import {createFractalCloudClient} from '@fractal_cloud/sdk/model';
const cloud = createFractalCloudClient({
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
});
await cloud.blueprints.create(fractal, {isPrivate: false});
await cloud.liveSystems.deploy(liveSystem, {mode: 'wait'});
| Operation | Description |
|---|---|
cloud.blueprints.create(fractal, opts?) | Upsert the blueprint (idempotent). opts.isPrivate keeps it out of the shared catalogue; default false. Accepts a base Fractal only — a specialization cannot be published. |
cloud.liveSystems.deploy(ls, opts?) | Create or update a Live System. Its blueprint must already be registered. |
cloud.liveSystems.outputs(ls | id) | Read the deployed per-component status and output fields. |
cloud.liveSystems.destroy(ls) | Destroy the Live System. Its blueprint stays registered. |
cloud.environments.deploy(management, opts?) | Deploy a management environment tree — see Environments. |
A blueprint carrying an Offer type is rejected before any network call: a 3-part type names a service delivery model, so it is vendor-locked and can never be re-satisfied by another vendor.
DeployOptions
| Option | Type | Default | Description |
|---|---|---|---|
mode | 'wait' | 'fire-and-forget' | 'fire-and-forget' | wait polls to Active and resolves with the Live System state. |
quiet | boolean | false | Suppress all SDK log output in wait mode (use when a CLI owns presentation). |
pollIntervalMs | number | 5000 | Poll interval in wait mode. |
timeoutMs | number | 600000 | Give up after this long and throw. |
fire-and-forget submits and returns immediately, emitting no logs. wait emits the canonical
wait-mode log contract.
Reading output fields
const state = await cloud.liveSystems.outputs(liveSystem);
const ip = state.components['vllm-host'].outputFields.privateIp;
| Type | Shape |
|---|---|
LiveSystemState | {status: string, components: Record<id, ComponentState>} |
ComponentState | {status: string, outputFields: Record<string, string>} |
Output fields are vendor-agnostic and identical in shape across clouds, and never contain raw
secrets — only references (*_REF) the runtime resolves at launch.
Wait-mode log format
[2026-03-10T14:23:01Z] INFO Deploying Live System system=<id> fractal=<id> provider=<AWS|Azure|...>
[2026-03-10T14:23:11Z] CHECK Polling Live System status system=<id> round=1 status=<status> elapsed=10s
[2026-03-10T14:23:31Z] INFO Live System Active system=<id> elapsed=30s
Append-only, no ANSI escapes, no cursor rewrites — safe for any CI log aggregator. Failure and
timeout emit ERROR lines carrying status / timeoutMs.
Extending the catalogue
Components and Offers are plain values, so an organization can add its own without forking the SDK.
Adding an Offer
import {defineOffer} from '@fractal_cloud/sdk/model';
const Ceph = defineOffer<'Storage.ObjectStorage', {storageClass?: string}>({
satisfies: 'Storage.ObjectStorage',
offerType: 'Storage.CaaS.Ceph',
deliveryModel: 'CaaS',
});
| Field | Type | Required | Description |
|---|---|---|---|
satisfies | Component tag | yes | Which Level-1 Component this Offer implements. |
offerType | string | yes | 3-part offer type Domain.DeliveryModel.Name. Must match the id the agent's handler registry is keyed on. |
provider | 'AWS' | 'Azure' | 'GCP' | 'OCI' | 'Hetzner' | 'Aruba' | 'RedHat' | 'VMware' | no | Omit for vendor-neutral self-hosted offers. |
deliveryModel | 'IaaS' | 'PaaS' | 'CaaS' | 'SaaS' | 'FaaS' | yes | Delivery model segment. |
instantiate | (ctx, config) => LiveSystemComponent[] | no | Emit a custom set of live components (e.g. a parent plus one child per ctx.children entry). Defaults to one component merging neutral params with vendor config. |
validate | (self, all, config) => void | no | Cross-component invariant, run once every component is emitted. Throw to refuse the Live System. |
Every existing Fractal can select a new Offer immediately — no blueprint changes.
Adding a Component
Author a factory on the core primitives (newNode, guardrail, addDependency), then write
Offers that satisfies it. Custom domains, components and vendors must be registered with the
Fractal Cloud platform before deployment succeeds.
Runnable end-to-end examples live in the per-language sample repositories — TypeScript, Java, Terraform.