Skip to main content

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.

ConceptWhat it does
FractalThe reusable, governed blueprint an infra team authors. References abstract Components only.
ComponentA Level-1 capability contract (Storage.ObjectStorage). Carries vendor-neutral parameters.
OfferA Level-3 concrete implementation (Storage.PaaS.AwsS3). Carries vendor knobs.
Live SystemA dev team's instantiation: one Offer selected per Component, deployed into an Environment.
ClientHolds 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

FieldTypeRequiredDescription
idstringyesFractal name. Combined with version into the fractal id name:major.minor.patch.
version{major, minor, patch}yesSemantic version of this blueprint revision.
boundedContextIdOwnerRefyesOwning Bounded Context — ownerType, ownerId, name.
descriptionstringnoHuman description. Defaults to a generated string.
blueprint(bp) => SlotsyesDeclares components and links; returns the named slots.
operations(slots, ctx) => OpsnoThe Fractal interface — the only customization a consumer may perform.

The bp handle (blueprint author)

MethodDescription
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)

MethodDescription
slots.<name>.idThe 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

FieldTypeRequiredDescription
namestringyesLive System name.
environmentOwnerRefyesTarget environment reference — management.ref() or management.operational(name).ref().
selectRecord<componentId, Offer>yesOne 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'});
OperationDescription
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

OptionTypeDefaultDescription
mode'wait' | 'fire-and-forget''fire-and-forget'wait polls to Active and resolves with the Live System state.
quietbooleanfalseSuppress all SDK log output in wait mode (use when a CLI owns presentation).
pollIntervalMsnumber5000Poll interval in wait mode.
timeoutMsnumber600000Give 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;
TypeShape
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',
});
FieldTypeRequiredDescription
satisfiesComponent tagyesWhich Level-1 Component this Offer implements.
offerTypestringyes3-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'noOmit for vendor-neutral self-hosted offers.
deliveryModel'IaaS' | 'PaaS' | 'CaaS' | 'SaaS' | 'FaaS'yesDelivery model segment.
instantiate(ctx, config) => LiveSystemComponent[]noEmit 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) => voidnoCross-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.

Samples

Runnable end-to-end examples live in the per-language sample repositories — TypeScript, Java, Terraform.