Quick Start
Prerequisites
Section titled “Prerequisites”- Rust stable (MSRV 1.75, recommended 1.88+)
- Python 3.11+ with
pip(for Sayiir workflow engine) - Docker (for Postgres, Ollama, Whisper)
- Node.js 18+ (for TypeScript SDK, optional)
brew install just protobuf1. Start Infrastructure
Section titled “1. Start Infrastructure”# Clone the repogit clone https://github.com/AriSteffworking/fabric.git && cd fabric
# Start Postgres + Ollama + Whisperjust infra-up
# Configure environmentcp .env.example .env2. Start the Server
Section titled “2. Start the Server”just devThe API starts on http://localhost:3001. Verify with:
curl http://localhost:3001/healthz# {"status":"ok"}3. Register Your App
Section titled “3. Register Your App”Every consumer app (your SaaS, your mobile app, your internal tool) registers with Fabric to get client credentials.
cargo run -p fabric -- setup \ --app-name "My App" \ --email "dev@myapp.com" \ --password "SecureP@ss1"Output:
Fabric setup complete.
App: My App (my-app) Admin: dev@myapp.com Organization: My App (swift-fox-742) Organization ID: 5fe20183-...
Add to your consumer app .env:
FABRIC_API_URL=http://localhost:3001 FABRIC_CLIENT_ID=foc_abc123... FABRIC_CLIENT_SECRET=focs_xyz789...4. Install the SDK
Section titled “4. Install the SDK”npm install @fabric-platform/sdkpip install fabric-workflow-sdkNo installation needed — use the REST API directly.
5. Initialize the Client
Section titled “5. Initialize the Client”import { FabricClient } from "@fabric-platform/sdk";
const fabric = new FabricClient({ baseUrl: "http://localhost:3001", app: { clientId: process.env.FABRIC_CLIENT_ID!, clientSecret: process.env.FABRIC_CLIENT_SECRET!, },});import osfrom fabric_platform import FabricClient
fabric = FabricClient( base_url="http://localhost:3001", api_key=os.environ["FABRIC_API_KEY"],)# All curl examples use the API key from setupexport FABRIC_URL=http://localhost:3001export API_KEY="fab_your_key_here"6. Sign Up a User
Section titled “6. Sign Up a User”Your app’s users sign up through Fabric. Fabric creates the user and a personal org scoped to your app.
// User signs up through your app's UIconst auth = await fabric.auth.signup("alice@example.com", "UserP@ss1");console.log("User:", auth.user.id);console.log("Access token:", auth.access_token);curl -X POST $FABRIC_URL/v1/auth/signup \ -H "Content-Type: application/json" \ -H "X-Fabric-App-Id: $FABRIC_CLIENT_ID" \ -d '{"email":"alice@example.com","password":"UserP@ss1"}'7. Act on Behalf of a User
Section titled “7. Act on Behalf of a User”Your server uses token exchange to get a user-scoped client:
// Token exchange: get a client scoped to this userconst userFabric = await fabric.asUser(auth.user.id);
// Submit a workflow as this userconst run = await userFabric.workflows.runs.submit("content/generate", { input: { topic: "AI trends in 2026", tone: "professional", },});console.log("Run:", run.id, run.status);# Step 1: Exchange app credentials for a user-scoped tokenTOKEN=$(curl -s -X POST $FABRIC_URL/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "token_exchange", "client_id": "'$FABRIC_CLIENT_ID'", "client_secret": "'$FABRIC_CLIENT_SECRET'", "subject_token": "'$USER_ID'", "subject_token_type": "urn:fabric:user_id" }' | jq -r '.data.access_token')
# Step 2: Use the token to submit a workflowcurl -X POST "$FABRIC_URL/v1/workflows/run?name=content/generate" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"input":{"topic":"AI trends in 2026","tone":"professional"}}'8. Watch the Workflow
Section titled “8. Watch the Workflow”// Watch the run step-by-stepconst watcher = userFabric.workflows.runs.watch(run.id, { onNodeStarted: (key) => console.log(`> ${key} started`), onNodeProgress: (key, p) => console.log(` ${key}: ${p.percentage}%`), onNodeCompleted: (key) => console.log(` ${key} done`), onRunCompleted: () => console.log("Workflow finished!"), onRunFailed: (p) => console.error("Failed:", p),});
// Wait for completionawait watcher.done;
// Get the resultconst result = await userFabric.workflows.runs.getResult(run.id);console.log("Output:", result.output);# Stream events via SSEcurl -N -H "Authorization: Bearer $TOKEN" \ "$FABRIC_URL/v1/workflow-runs/$RUN_ID/events"9. Receive Webhooks
Section titled “9. Receive Webhooks”Set up a webhook to get notified when workflows complete:
import { createWebhookHandler } from "@fabric-platform/sdk";
// In your Next.js/Express route handlerexport const POST = createWebhookHandler( process.env.WEBHOOK_SECRET!, { "workflow.run.completed": async (event) => { console.log("Run completed:", event.run_id); const result = await fabric.workflows.runs.getResult(event.run_id!, { includeArtifacts: true, }); console.log("Output:", result.output); console.log("Download:", result.primaryDownloadUrl); }, "workflow.run.failed": async (event) => { console.error("Run failed:", event.payload); }, },);# Register a webhookcurl -X POST "$FABRIC_URL/v1/organizations/$ORG_ID/webhooks" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://myapp.com/api/webhooks/fabric", "event_filter": ["workflow.run.completed", "workflow.run.failed"] }'Dev Mode Shortcuts
Section titled “Dev Mode Shortcuts”During local development, you can skip the full OAuth flow and use dev-header auth:
# Dev mode: authenticate with X-Principal-Id header (no JWT needed)export AUTH="-H 'X-Principal-Id: 00000000-0000-0000-0000-000000000001'"
# List providerscurl $AUTH http://localhost:3001/v1/providers
# Create an orgcurl $AUTH -X POST http://localhost:3001/v1/organizations \ -H 'content-type: application/json' \ -d '{"slug":"acme","name":"Acme Corp"}'
# Run the example pipelinejust example-pipelineWhat’s Next?
Section titled “What’s Next?”- App Registration Guide — Deep dive into app setup, user auth, token exchange, and org isolation
- TypeScript SDK Reference — Complete SDK API with all 20+ resource classes
- Configuration — Environment variables, Docker profiles, and deployment options
- Workflow Authoring — Build custom AI workflows with the Python SDK
- Streaming Events — Real-time event streaming via SSE and WebSocket