@labsfoundry/sdk is a strict TypeScript SDK for converting product requirements into validated, machine-readable software architecture plans. It combines provider-backed design generation with deterministic validation and diagram generation.
Keep provider API keys on trusted servers. Never expose OpenAI or external API credentials in browser bundles.
| Capability | Provider Call | Deterministic | Browser-Safe Core |
|---|---|---|---|
| Generate a system design | Yes | No | No |
| Refine an existing design | Yes | No | No |
| Compare designs | Yes | No | No |
| Estimate complexity and cost ranges | Yes | No | No |
| Validate design structure and quality | No | Yes | Yes |
| Generate Mermaid or JSON diagrams | No | Yes | Yes |
| Validate provider output with Zod | No additional call | Yes | Yes |
| Query an optional technology catalog | External HTTP | No | Native fetch |
All provider results cross a Zod validation boundary before being returned. The default OpenAI provider requests structured output and then validates the parsed result again locally.
flowchart LR
App["Server application"] --> Client["Foundry client"]
Client --> Systems["systems API"]
Client --> Diagrams["diagrams API"]
Client --> Registry["provider registry"]
Systems --> Input["Zod input validation"]
Input --> AI["AIProvider"]
AI --> OpenAI["OpenAIProvider"]
AI --> Custom["Custom provider"]
OpenAI --> Structured["Structured provider response"]
Custom --> Structured
Structured --> Output["Zod output validation"]
Output --> Design["SystemDesign"]
Design --> Validator["Deterministic validator"]
Design --> Diagrams
Validator --> Report["Validation report"]
Diagrams --> Mermaid["Mermaid text"]
Diagrams --> JSON["JSON graph"]
Registry -. optional .-> Tech["TechnologyDataProvider"]
Tech --> Catalog["External technology catalog"]
sequenceDiagram
participant App as Application
participant SDK as Foundry
participant Schema as Zod
participant Retry as Retry/timeout layer
participant Provider as AIProvider
App->>SDK: systems.generate(input, options)
SDK->>Schema: validate GenerateSystemInput
alt invalid input
Schema-->>App: ValidationError
else valid input
SDK->>Retry: execute bounded request
Retry->>Provider: generateSystemDesign
Provider-->>Retry: structured response
Retry-->>SDK: provider result
SDK->>Schema: validate SystemDesign
alt malformed output
Schema-->>App: validation failure
else valid output
SDK-->>App: SystemDesign
end
end
Requirements:
-
Node.js 20 or newer
-
A server runtime for the default OpenAI provider
-
An OpenAI API key, or a custom
AIProvider
npm install @labsfoundry/sdk
The package publishes ESM, CommonJS, declarations, and source maps:
import { Foundry } from "@labsfoundry/sdk";const { Foundry } = require("@labsfoundry/sdk");import { Foundry } from "@labsfoundry/sdk";
const foundry = new Foundry({
apiKey: process.env.OPENAI_API_KEY!,
model: process.env.OPENAI_MODEL ?? "gpt-5-mini",
});
const design = await foundry.systems.generate({
name: "Multiplayer Survival Game",
description:
"A multiplayer survival game supporting 200 concurrent players with voice chat, inventory, authentication, analytics, and Solana payments.",
requirements: ["Players can join persistent worlds", "Payments must be auditable"],
constraints: {
concurrentUsers: 200,
regions: ["us-east", "eu-west"],
budget: "medium",
teamSize: 6,
availabilityTarget: 99.9,
latencyTargetMs: 150,
},
preferences: {
languages: ["TypeScript"],
cloudProviders: ["AWS"],
avoid: ["self-managed Kubernetes"],
},
});
const validation = foundry.systems.validate(design);
const mermaid = foundry.diagrams.generate(design, {
format: "mermaid",
type: "architecture",
});
console.log({ design, validation, mermaid });The library does not read environment variables automatically. Applications explicitly pass configuration, which keeps environment handling under application control.
OPENAI_API_KEY=
OPENAI_MODEL=gpt-5-mini
OPENAI_BASE_URL=
FOUNDRY_TECH_API_URL=
FOUNDRY_TECH_API_KEY=
interface FoundryConfig {
apiKey?: string;
model?: string;
provider?: AIProvider;
technologyDataProvider?: TechnologyDataProvider;
timeoutMs?: number;
maxRetries?: number;
baseUrl?: string;
logger?: Logger;
userAgent?: string;
}| Option | Type | Default | Notes |
|---|---|---|---|
apiKey |
string |
— | Required unless provider is supplied |
model |
string |
gpt-5-mini |
Model used by OpenAIProvider |
provider |
AIProvider |
OpenAIProvider |
Replaces the default AI provider |
technologyDataProvider |
TechnologyDataProvider |
— | Exposed through foundry.providers.technology |
timeoutMs |
number |
30000 |
Default timeout for each provider call |
maxRetries |
number |
2 |
Retry attempts after the initial request |
baseUrl |
string |
OpenAI default | Useful with compatible API gateways |
logger |
Logger |
Silent | Must not log sensitive payloads |
userAgent |
string |
Provider default | Optional HTTP user-agent value |
Configuration is checked synchronously. Construction fails if credentials and a custom provider are both absent, if timeoutMs <= 0, or if maxRetries is not a non-negative integer.
const foundry = new Foundry({
provider: new InternalArchitectureProvider(),
timeoutMs: 45_000,
maxRetries: 3,
});Generates and validates a complete design.
interface GenerateSystemInput {
name: string;
description: string;
requirements?: string[];
constraints?: SystemConstraints;
preferences?: TechnologyPreferences;
context?: Record<string, unknown>;
}Key input limits include a 200-character name, a description between 10 and 50,000 characters, bounded lists, and a maximum serialized provider prompt size of 500,000 characters.
const design: SystemDesign = await foundry.systems.generate(input, {
timeoutMs: 60_000,
signal: abortController.signal,
});Requests structural changes while preserving the SystemDesign contract.
const result = await foundry.systems.refine({
design,
instruction: "Reduce infrastructure cost and replace Kubernetes with managed containers.",
});
// result.design: SystemDesign
// result.changes: Array<{ path; description; reason }>The instruction must contain 1–20,000 characters. The source design and refined result are validated.
Runs synchronously without credentials, network access, or an AI request.
const result = foundry.systems.validate(design);
if (!result.valid) {
for (const issue of result.errors) {
console.error(issue.code, issue.path, issue.message);
}
}Returns:
interface SystemValidationResult {
valid: boolean;
score: number; // 0–100
errors: ValidationIssue[];
warnings: ValidationIssue[];
suggestions: ValidationIssue[];
}Compares 2–10 validated designs. Criteria scores use a 0–100 scale.
const comparison = await foundry.systems.compare({
designs: [designA, designB],
priorities: ["cost", "scalability", "developer experience"],
});recommendedDesignId is nullable when the evidence does not support a clear winner.
Returns directional ranges for team size, implementation time, and monthly infrastructure cost, plus complexity, operational burden, cost drivers, assumptions, confidence, and a mandatory disclaimer.
const estimate = await foundry.systems.estimate({ design });
console.log(estimate.estimatedTimelineWeeks.min);
console.log(estimate.infrastructureCostMonthlyUsd.max);Estimates are engineering planning aids, not quotes or financial guarantees.
Overloads preserve the output type:
const source: string = foundry.diagrams.generate(design, {
format: "mermaid",
type: "data-flow",
});
const graph: JsonDiagram = foundry.diagrams.generate(design, {
format: "json",
type: "architecture",
});Supported types: architecture, sequence, deployment, data-flow, and entity-relationship.
classDiagram
class SystemDesign {
string id
string name
string summary
string architectureStyle
string[] assumptions
}
class SystemComponent {
string id
string[] responsibilities
string[] dependencies
string[] failureHandling
string scalingStrategy
}
class DatabaseRecommendation {
string ownerComponentId
string purpose
string backupStrategy
Entity[] entities
}
class ApiDefinition {
string componentId
boolean protected
object requestSchema
object responseSchema
}
class DataFlow {
string sourceComponentId
string targetComponentId
string protocol
}
class ArchitectureDiagram {
Node[] nodes
Edge[] edges
}
SystemDesign "1" *-- "many" SystemComponent
SystemDesign "1" *-- "many" DatabaseRecommendation
SystemDesign "1" *-- "many" ApiDefinition
SystemDesign "1" *-- "many" DataFlow
SystemDesign "1" *-- "many" ArchitectureDiagram
SystemComponent "1" <-- "many" DatabaseRecommendation : owner
SystemComponent "1" <-- "many" ApiDefinition : serves
| Section | Purpose |
|---|---|
requirements |
Functional and non-functional requirements |
technologyStack |
Purpose, rationale, alternatives, and risks |
components |
Responsibilities, dependencies, failure handling, and scaling |
databases |
Ownership, entities, consistency, backups, and retention |
apis |
Protocols, endpoints, authentication, schemas, and errors |
dataFlows |
Sources, targets, data, protocols, security, and failures |
infrastructure |
Providers, regions, targets, compute, storage, and disaster recovery |
deployment |
Environments, CI/CD, releases, and rollback |
security |
Authentication, authorization, encryption, secrets, and threats |
scalability |
Scaling, caching, partitioning, bottlenecks, and triggers |
observability |
Logs, metrics, traces, alerts, dashboards, and SLOs |
risks and tradeoffs |
Explicit uncertainty and architectural decisions |
implementationPhases |
Ordered goals, deliverables, duration ranges, and risks |
metadata |
Timestamp, model, provider, and SDK version |
All public schemas are exported, so persistence and API layers can reuse the same contracts:
import { SystemDesignSchema, type SystemDesign } from "@labsfoundry/sdk";
const design: SystemDesign = SystemDesignSchema.parse(untrustedJson);flowchart TD
Start["Unknown input"] --> Schema{"SystemDesign schema valid?"}
Schema -- No --> SchemaErrors["Schema errors with paths"]
Schema -- Yes --> Graph["Build component dependency graph"]
Graph --> References["Check component, API, DB, and flow references"]
References --> Cycles["Detect circular dependencies"]
Cycles --> Quality["Check security, backup, scaling, failures, observability"]
Quality --> Score["Calculate quality score"]
SchemaErrors --> Result["SystemValidationResult"]
Score --> Result
Validation covers:
-
missing components and responsibilities
-
undefined and circular component dependencies
-
protected APIs without authentication
-
APIs without request or response schemas
-
databases without a valid owner, purpose, or backup strategy
-
infrastructure without deployment targets
-
absent logging, metrics, or alerting
-
missing failure handling and component scaling strategies
-
missing scaling approach and capacity triggers
-
absent security controls
-
very high availability claims without disaster recovery detail
-
explicit technology compatibility risks and duplicate recommendations
Scoring starts at 100 and deducts 15 per error, 5 per warning, and 2 per suggestion, with a minimum of zero. valid means there are no errors; warnings can still be present.
Diagram generation is deterministic. It never sends the design to a provider.
| Type | Source data | Mermaid form |
| --------------------- | -------------------------------------- | ----------------- |
| architecture | Components and dependencies | flowchart LR |
| sequence | Components and dependency interactions | sequenceDiagram |
| deployment | Current component graph | flowchart LR |
| data-flow | Structured dataFlows | flowchart LR |
| entity-relationship | Database entities | erDiagram |
Mermaid IDs are reduced to alphanumeric/underscore identifiers. Labels remove control-sensitive punctuation and line breaks and are capped at 120 characters. Render generated text using Mermaid in your own documentation or UI layer.
interface AIProvider {
readonly name: string;
generateSystemDesign(input, options?): Promise<SystemDesign>;
refineSystemDesign(input, options?): Promise<RefineSystemResult>;
compareSystemDesigns(input, options?): Promise<DesignComparison>;
estimateSystem(input, options?): Promise<SystemEstimate>;
}OpenAIProvider uses the official OpenAI Node.js SDK, structured responses, local Zod validation, an application-controlled API key, and a default model of gpt-5-mini. Provider instructions require explicit assumptions and tradeoffs, consistent IDs, authenticated protected APIs, failure handling, backups, scaling, security, and observability.
import { OpenAIProvider, Foundry } from "@labsfoundry/sdk";
const provider = new OpenAIProvider({
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-5-mini",
timeoutMs: 30_000,
maxRetries: 2,
});
const foundry = new Foundry({ provider });import {
Foundry,
SystemDesignSchema,
type AIProvider,
type GenerateSystemInput,
type ProviderRequestOptions,
} from "@labsfoundry/sdk";
class InternalProvider implements AIProvider {
readonly name = "internal";
async generateSystemDesign(input: GenerateSystemInput, options?: ProviderRequestOptions) {
const response = await fetch("https://architecture.example/designs", {
method: "POST",
signal: options?.signal,
headers: { "content-type": "application/json" },
body: JSON.stringify(input),
});
if (!response.ok) throw new Error(`Provider failed: ${response.status}`);
return SystemDesignSchema.parse(await response.json());
}
// Implement refineSystemDesign, compareSystemDesigns, and estimateSystem
// with their exported schemas and result types.
}
const foundry = new Foundry({ provider: new InternalProvider() });A complete implementation is available in examples/custom-provider/index.ts.
The technology provider is optional and independent from the AI provider. It is available at foundry.providers.technology; applications decide when and how enrichment is merged into recommendations.
import { Foundry, HttpTechnologyDataProvider } from "@labsfoundry/sdk";
const technologyDataProvider = new HttpTechnologyDataProvider({
baseUrl: process.env.FOUNDRY_TECH_API_URL!,
apiKey: process.env.FOUNDRY_TECH_API_KEY,
timeoutMs: 10_000,
paths: {
search: "/technologies/search",
technology: "/technologies",
},
});
const foundry = new Foundry({
apiKey: process.env.OPENAI_API_KEY!,
technologyDataProvider,
});
const matches = await foundry.providers.technology?.searchTechnologies({
query: "PostgreSQL",
runtime: "node20",
limit: 5,
});Default HTTP contract:
| Operation | Request | Response |
| --------- | -------------------------------------------------------- | ------------------------------- |
| Search | POST /technologies/search with TechnologySearchQuery | TechnologySearchResult[] |
| Detail | GET /technologies/:identifier | TechnologyDetails or HTTP 404 |
The adapter accepts custom paths and a custom fetch implementation. Responses larger than 1 MB are rejected. No technology API is required for core SDK operation.
stateDiagram-v2
[*] --> Attempt
Attempt --> Success: valid response
Attempt --> Aborted: AbortSignal
Attempt --> Failed: permanent failure
Attempt --> Backoff: transient failure and retries remain
Backoff --> Attempt: exponential delay plus jitter
Attempt --> TimedOut: timeout reached
Success --> [*]
Aborted --> [*]
Failed --> [*]
TimedOut --> [*]
Retryable conditions:
-
network failures
-
HTTP 408, 429, 500, 502, 503, and 504
-
provider timeouts when retries remain
Non-retryable conditions:
-
invalid API credentials
-
malformed user input
-
Zod validation failures
-
malformed provider output
-
explicit request cancellation
Request options override the client timeout:
const controller = new AbortController();
const pending = foundry.systems.generate(input, {
signal: controller.signal,
timeoutMs: 60_000,
});
controller.abort();
await pending;
FoundryError
├── ConfigurationError
├── ValidationError
├── ProviderError
│ ├── ProviderAuthenticationError
│ ├── ProviderRateLimitError
│ ├── ProviderTimeoutError
│ └── ProviderResponseError
├── ExternalApiError
└── AbortError
Every SDK error exposes code, message, retryable, and optional statusCode, cause, and safe details.
import { FoundryError, ProviderRateLimitError } from "@labsfoundry/sdk";
try {
await foundry.systems.generate(input);
} catch (error) {
if (error instanceof ProviderRateLimitError && error.retryable) {
// Queue for a later application-level attempt.
} else if (error instanceof FoundryError) {
console.error(error.code, error.statusCode);
}
}The default logger is silent. Custom loggers must never emit credentials, authorization headers, full prompts, private application context, or raw provider responses.
| Control | Implementation |
| ------------------------- | ------------------------------------------------------------------------- |
| Secret isolation | Provider construction is documented as server-only |
| Input validation | Strict Zod objects with length and numeric bounds |
| Output validation | Structured provider output plus local Zod parsing |
| Prompt injection boundary | Provider instructions treat descriptions as untrusted data |
| Credential redaction | Key/token/authorization-like fields and common token strings are redacted |
| Request cancellation | Standard AbortSignal support |
| Resource limits | Prompt serialization and external response caps |
| Mermaid safety | Sanitized node IDs and labels |
| Code execution | No eval, shell execution, or dynamic code loading |
| Deserialization | JSON parsing followed by schema validation at SDK boundaries |
-
Server-only:
Foundry,OpenAIProvider, and any code holding provider credentials. -
Browser-safe logic: exported Zod schemas,
validateSystemDesign,generateDiagram, and public utility types. -
Runtime-dependent:
HttpTechnologyDataProviderrequires nativefetchor an injected implementation.
Do not instantiate Foundry with a secret inside React client components, browser bundles, service-worker source, or publicly executable edge code where environment secrets are exposed.
| Example | Location | Demonstrates |
| ------------------- | ------------------------------ | --------------------------------------- |
| Basic Node | examples/basic-node | Generation and Mermaid output |
| Advanced operations | examples/advanced-operations | Refine, compare, estimate, cancellation |
| Express | examples/express-api | Server endpoint integration |
| Next.js | examples/nextjs-route | App Router server route |
| Custom AI provider | examples/custom-provider | Complete provider adapter |
| Technology provider | examples/technology-provider | In-memory catalog adapter |
From a repository checkout:
npm install
npm install --save-dev tsx express @types/express
npx tsx examples/basic-node/index.ts
npx tsx examples/advanced-operations/index.ts
npx tsx examples/express-api/server.ts
For Next.js, copy examples/nextjs-route/route.ts into app/api/design/route.ts in an existing server-rendered Next.js application.
sdk/
├── src/
│ ├── foundry.ts # Public client and APIs
│ ├── openai-provider.ts # Default provider
│ ├── technology-provider.ts # Generic HTTP catalog adapter
│ ├── schemas.ts # Zod source of truth
│ ├── types.ts # Inferred and interface types
│ ├── validation.ts # Deterministic design checks
│ ├── diagrams.ts # Mermaid and JSON graphs
│ ├── errors.ts # Typed errors and mapping
│ ├── utils.ts # Retry, timeout, redaction
│ └── index.ts # Public exports
├── tests/ # Offline unit/integration tests
├── examples/ # Server and provider examples
├── scripts/verify-package.mjs # Built entry-point check
└── dist/ # ESM, CommonJS, declarations, maps
npm install
npm run typecheck
npm run lint
npm test
npm run build
npm run verify:package
npm pack --dry-run
npm run check runs type checking, linting, tests, and the build in sequence. Tests do not require external credentials. A real OpenAI integration test should only be enabled in a controlled environment with an explicit test key.
npm login
npm run check
npm run verify:package
npm pack --dry-run
npm publish --access public
Verify that the npm account has permission to publish the @labsfoundry scope and that the version does not already exist before publishing.
See CONTRIBUTING.md. Keep schemas as the source of truth, avoid duplicated public types, add deterministic tests for behavior changes, and run the full quality gate before submitting changes.
MIT. See LICENSE.
Foundry provides engineering recommendations. It does not guarantee security, regulatory compliance, infrastructure cost, availability, performance, or production fitness. Qualified humans must review architecture, security, compliance, capacity, and commercial decisions before production use.