diff --git a/apps/docs/app/llms.txt/route.ts b/apps/docs/app/llms.txt/route.ts
index 969a5c97260..f172dd07156 100644
--- a/apps/docs/app/llms.txt/route.ts
+++ b/apps/docs/app/llms.txt/route.ts
@@ -62,7 +62,7 @@ ${Object.entries(sections)
- Full documentation content: ${baseUrl}/llms-full.txt
- Individual page content: ${baseUrl}/llms.mdx/[page-path]
-- API documentation: ${baseUrl}/sdks/
+- API documentation: ${baseUrl}/api-reference/
- Tool integrations: ${baseUrl}/tools/
## Statistics
diff --git a/apps/docs/content/docs/de/index.mdx b/apps/docs/content/docs/de/index.mdx
index 92ebaf1f632..d6f678e658c 100644
--- a/apps/docs/content/docs/de/index.mdx
+++ b/apps/docs/content/docs/de/index.mdx
@@ -51,7 +51,7 @@ Willkommen bei Sim, einem visuellen Workflow-Builder für KI-Anwendungen. Erstel
Externe Dienste mit dem Model Context Protocol verbinden
-
+
Sim in Ihre Anwendungen integrieren
\ No newline at end of file
diff --git a/apps/docs/content/docs/en/api-reference/python.mdx b/apps/docs/content/docs/en/api-reference/python.mdx
index 3ab1cdee763..903bac51f1c 100644
--- a/apps/docs/content/docs/en/api-reference/python.mdx
+++ b/apps/docs/content/docs/en/api-reference/python.mdx
@@ -65,14 +65,14 @@ Execute a workflow with optional input data.
```python
result = client.execute_workflow(
"workflow-id",
- input_data={"message": "Hello, world!"},
+ input={"message": "Hello, world!"},
timeout=30.0 # 30 seconds
)
```
**Parameters:**
- `workflow_id` (str): The ID of the workflow to execute
-- `input_data` (dict, optional): Input data to pass to the workflow
+- `input` (dict, optional): Input data to pass to the workflow
- `timeout` (float, optional): Timeout in seconds (default: 30.0)
- `stream` (bool, optional): Enable streaming responses (default: False)
- `selected_outputs` (list[str], optional): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
@@ -144,7 +144,7 @@ Execute a workflow with automatic retry on rate limit errors using exponential b
```python
result = client.execute_with_retry(
"workflow-id",
- input_data={"message": "Hello"},
+ input={"message": "Hello"},
timeout=30.0,
max_retries=3, # Maximum number of retries
initial_delay=1.0, # Initial delay in seconds
@@ -155,7 +155,7 @@ result = client.execute_with_retry(
**Parameters:**
- `workflow_id` (str): The ID of the workflow to execute
-- `input_data` (dict, optional): Input data to pass to the workflow
+- `input` (dict, optional): Input data to pass to the workflow
- `timeout` (float, optional): Timeout in seconds
- `stream` (bool, optional): Enable streaming responses
- `selected_outputs` (list, optional): Block outputs to stream
@@ -359,7 +359,7 @@ def run_workflow():
# Execute the workflow
result = client.execute_workflow(
"my-workflow-id",
- input_data={
+ input={
"message": "Process this data",
"user_id": "12345"
}
@@ -488,7 +488,7 @@ def execute_async():
# Start async execution
result = client.execute_workflow(
"workflow-id",
- input_data={"data": "large dataset"},
+ input={"data": "large dataset"},
async_execution=True # Execute asynchronously
)
@@ -533,7 +533,7 @@ def execute_with_retry_handling():
# Automatically retries on rate limit
result = client.execute_with_retry(
"workflow-id",
- input_data={"message": "Process this"},
+ input={"message": "Process this"},
max_retries=5,
initial_delay=1.0,
max_delay=60.0,
@@ -615,7 +615,7 @@ def execute_with_streaming():
# Enable streaming for specific block outputs
result = client.execute_workflow(
"workflow-id",
- input_data={"message": "Count to five"},
+ input={"message": "Count to five"},
stream=True,
selected_outputs=["agent1.content"] # Use blockName.attribute format
)
@@ -758,4 +758,15 @@ Configure the client using environment variables:
## License
-Apache-2.0
\ No newline at end of file
+Apache-2.0
+
+import { FAQ } from '@/components/ui/faq'
+
+
\ No newline at end of file
diff --git a/apps/docs/content/docs/en/api-reference/typescript.mdx b/apps/docs/content/docs/en/api-reference/typescript.mdx
index 6364384c8b4..476cfb964d4 100644
--- a/apps/docs/content/docs/en/api-reference/typescript.mdx
+++ b/apps/docs/content/docs/en/api-reference/typescript.mdx
@@ -78,16 +78,15 @@ new SimStudioClient(config: SimStudioConfig)
Execute a workflow with optional input data.
```typescript
-const result = await client.executeWorkflow('workflow-id', {
- input: { message: 'Hello, world!' },
+const result = await client.executeWorkflow('workflow-id', { message: 'Hello, world!' }, {
timeout: 30000 // 30 seconds
});
```
**Parameters:**
- `workflowId` (string): The ID of the workflow to execute
+- `input` (any, optional): Input data to pass to the workflow
- `options` (ExecutionOptions, optional):
- - `input` (any): Input data to pass to the workflow
- `timeout` (number): Timeout in milliseconds (default: 30000)
- `stream` (boolean): Enable streaming responses (default: false)
- `selectedOutputs` (string[]): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
@@ -158,8 +157,7 @@ if (status.status === 'completed') {
Execute a workflow with automatic retry on rate limit errors using exponential backoff.
```typescript
-const result = await client.executeWithRetry('workflow-id', {
- input: { message: 'Hello' },
+const result = await client.executeWithRetry('workflow-id', { message: 'Hello' }, {
timeout: 30000
}, {
maxRetries: 3, // Maximum number of retries
@@ -171,6 +169,7 @@ const result = await client.executeWithRetry('workflow-id', {
**Parameters:**
- `workflowId` (string): The ID of the workflow to execute
+- `input` (any, optional): Input data to pass to the workflow
- `options` (ExecutionOptions, optional): Same as `executeWorkflow()`
- `retryOptions` (RetryOptions, optional):
- `maxRetries` (number): Maximum number of retries (default: 3)
@@ -389,10 +388,8 @@ async function runWorkflow() {
// Execute the workflow
const result = await client.executeWorkflow('my-workflow-id', {
- input: {
message: 'Process this data',
userId: '12345'
- }
});
if (result.success) {
@@ -508,8 +505,7 @@ app.post('/execute-workflow', async (req, res) => {
try {
const { workflowId, input } = req.body;
- const result = await client.executeWorkflow(workflowId, {
- input,
+ const result = await client.executeWorkflow(workflowId, input, {
timeout: 60000
});
@@ -555,8 +551,7 @@ export default async function handler(
try {
const { workflowId, input } = req.body;
- const result = await client.executeWorkflow(workflowId, {
- input,
+ const result = await client.executeWorkflow(workflowId, input, {
timeout: 30000
});
@@ -586,9 +581,7 @@ const client = new SimStudioClient({
async function executeClientSideWorkflow() {
try {
const result = await client.executeWorkflow('workflow-id', {
- input: {
userInput: 'Hello from browser'
- }
});
console.log('Workflow result:', result);
@@ -642,10 +635,8 @@ Alternatively, you can manually provide files using the URL format:
// Include files under the field name from your API trigger's input format
const result = await client.executeWorkflow('workflow-id', {
- input: {
documents: files, // Must match your workflow's "files" field name
instructions: 'Analyze these documents'
- }
});
console.log('Result:', result);
@@ -669,10 +660,8 @@ Alternatively, you can manually provide files using the URL format:
// Include files under the field name from your API trigger's input format
const result = await client.executeWorkflow('workflow-id', {
- input: {
documents: [file], // Must match your workflow's "files" field name
query: 'Summarize this document'
- }
});
```
@@ -712,8 +701,7 @@ export function useWorkflow(): UseWorkflowResult {
setResult(null);
try {
- const workflowResult = await client.executeWorkflow(workflowId, {
- input,
+ const workflowResult = await client.executeWorkflow(workflowId, input, {
timeout: 30000
});
setResult(workflowResult);
@@ -774,8 +762,7 @@ const client = new SimStudioClient({
async function executeAsync() {
try {
// Start async execution
- const result = await client.executeWorkflow('workflow-id', {
- input: { data: 'large dataset' },
+ const result = await client.executeWorkflow('workflow-id', { data: 'large dataset' }, {
async: true // Execute asynchronously
});
@@ -823,9 +810,7 @@ const client = new SimStudioClient({
async function executeWithRetryHandling() {
try {
// Automatically retries on rate limit
- const result = await client.executeWithRetry('workflow-id', {
- input: { message: 'Process this' }
- }, {
+ const result = await client.executeWithRetry('workflow-id', { message: 'Process this' }, {}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
@@ -908,8 +893,7 @@ const client = new SimStudioClient({
async function executeWithStreaming() {
try {
// Enable streaming for specific block outputs
- const result = await client.executeWorkflow('workflow-id', {
- input: { message: 'Count to five' },
+ const result = await client.executeWorkflow('workflow-id', { message: 'Count to five' }, {
stream: true,
selectedOutputs: ['agent1.content'] // Use blockName.attribute format
});
@@ -1033,3 +1017,14 @@ function StreamingWorkflow() {
## License
Apache-2.0
+
+import { FAQ } from '@/components/ui/faq'
+
+
diff --git a/apps/docs/content/docs/en/custom-tools/index.mdx b/apps/docs/content/docs/en/custom-tools/index.mdx
deleted file mode 100644
index b73dd33c768..00000000000
--- a/apps/docs/content/docs/en/custom-tools/index.mdx
+++ /dev/null
@@ -1,100 +0,0 @@
----
-title: Custom Tools
-description: Extend your agents with your own functions — defined by a schema and executed as JavaScript
----
-
-import { Image } from '@/components/ui/image'
-import { Callout } from 'fumadocs-ui/components/callout'
-
-Custom Tools let you define your own functions that agents can call, without needing an external MCP server. You write a JSON schema describing the function and the JavaScript code that runs when the agent invokes it.
-
-## What Is a Custom Tool?
-
-A custom tool has three parts:
-
-| Part | Description |
-|------|-------------|
-| **Schema** | OpenAI function-calling format — name, description, and parameters. This is what the agent sees when deciding whether to call the tool. |
-| **Code** | JavaScript that runs when the tool is called. Parameters come in as variables matching the schema. |
-| **Scope** | Custom tools are workspace-scoped and available to every agent in that workspace. |
-
-Use custom tools when you need tightly-scoped logic that doesn't warrant spinning up a full MCP server — one-off API calls, formatting helpers, internal utilities, etc.
-
-## Creating a Custom Tool
-
-1. Navigate to **Settings → Custom Tools**
-2. Click **Add**
-3. Fill out the **Schema** tab with your function definition
-
-
-
-
-
-
-Use the **Generate** button to have AI draft the schema from a plain-English description.
-
-
-4. Write your implementation in the **Code** tab
-5. Click **Save**
-
-
-You can also create a custom tool directly from an Agent block — click **Add tool… → Create Tool** in the tool dropdown.
-
-
-## Schema Format
-
-Custom tool schemas follow the OpenAI function-calling spec:
-
-```json
-{
- "type": "function",
- "function": {
- "name": "get_weather",
- "description": "Get the current weather for a city",
- "parameters": {
- "type": "object",
- "properties": {
- "city": {
- "type": "string",
- "description": "The city to get weather for"
- }
- },
- "required": ["city"]
- }
- }
-}
-```
-
-The `name` must be lowercase, use underscores, and match what your code expects as input.
-
-## Using Custom Tools in Agents
-
-Once created, your tools become available in any Agent block:
-
-1. Open an **Agent** block
-2. In the **Tools** section, click **Add tool…**
-3. Under **Custom Tools**, click the tool you want to add
-4. The agent can now call the tool the same way it calls MCP tools or built-in tools
-
-## Custom Tools vs MCP Tools
-
-| | **Custom Tools** | **MCP Tools** |
-|---|---|---|
-| **Defined** | Inline — schema + code in Sim | External MCP server |
-| **Hosting** | Runs inside Sim | Runs on your server |
-| **Best for** | Small, workspace-specific helpers | Shared tools, third-party services, complex integrations |
-| **Setup** | One modal | Deploy and register a server |
-
-## Permission Requirements
-
-| Action | Required Permission |
-|--------|-------------------|
-| Create or update custom tools | **Write** or **Admin** |
-| Delete custom tools | **Admin** |
-| Use custom tools in agents | **Read**, **Write**, or **Admin** |
diff --git a/apps/docs/content/docs/en/index.mdx b/apps/docs/content/docs/en/index.mdx
index 6ad3ec93550..ee56612ae3a 100644
--- a/apps/docs/content/docs/en/index.mdx
+++ b/apps/docs/content/docs/en/index.mdx
@@ -51,7 +51,7 @@ Welcome to Sim, the open-source AI workspace where teams build, deploy, and mana
Connect external services with Model Context Protocol
-
+
Integrate Sim into your applications
\ No newline at end of file
diff --git a/apps/docs/content/docs/en/meta.json b/apps/docs/content/docs/en/meta.json
index 53ba23da826..24eb6eba869 100644
--- a/apps/docs/content/docs/en/meta.json
+++ b/apps/docs/content/docs/en/meta.json
@@ -21,7 +21,6 @@
"variables",
"integrations",
"credentials",
- "custom-tools",
"---Platform---",
"execution",
"permissions",
diff --git a/apps/docs/content/docs/en/sdks/meta.json b/apps/docs/content/docs/en/sdks/meta.json
deleted file mode 100644
index a46a15897f8..00000000000
--- a/apps/docs/content/docs/en/sdks/meta.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "title": "SDKs",
- "pages": ["python", "typescript"]
-}
diff --git a/apps/docs/content/docs/en/sdks/python.mdx b/apps/docs/content/docs/en/sdks/python.mdx
deleted file mode 100644
index 903bac51f1c..00000000000
--- a/apps/docs/content/docs/en/sdks/python.mdx
+++ /dev/null
@@ -1,772 +0,0 @@
----
-title: Python
----
-
-import { Callout } from 'fumadocs-ui/components/callout'
-import { Card, Cards } from 'fumadocs-ui/components/card'
-import { Step, Steps } from 'fumadocs-ui/components/steps'
-import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
-
-The official Python SDK for Sim allows you to execute workflows programmatically from your Python applications using the official Python SDK.
-
-
- The Python SDK supports Python 3.8+ with async execution support, automatic rate limiting with exponential backoff, and usage tracking.
-
-
-## Installation
-
-Install the SDK using pip:
-
-```bash
-pip install simstudio-sdk
-```
-
-## Quick Start
-
-Here's a simple example to get you started:
-
-```python
-from simstudio import SimStudioClient
-
-# Initialize the client
-client = SimStudioClient(
- api_key="your-api-key-here",
- base_url="https://sim.ai" # optional, defaults to https://sim.ai
-)
-
-# Execute a workflow
-try:
- result = client.execute_workflow("workflow-id")
- print("Workflow executed successfully:", result)
-except Exception as error:
- print("Workflow execution failed:", error)
-```
-
-## API Reference
-
-### SimStudioClient
-
-#### Constructor
-
-```python
-SimStudioClient(api_key: str, base_url: str = "https://sim.ai")
-```
-
-**Parameters:**
-- `api_key` (str): Your Sim API key
-- `base_url` (str, optional): Base URL for the Sim API
-
-#### Methods
-
-##### execute_workflow()
-
-Execute a workflow with optional input data.
-
-```python
-result = client.execute_workflow(
- "workflow-id",
- input={"message": "Hello, world!"},
- timeout=30.0 # 30 seconds
-)
-```
-
-**Parameters:**
-- `workflow_id` (str): The ID of the workflow to execute
-- `input` (dict, optional): Input data to pass to the workflow
-- `timeout` (float, optional): Timeout in seconds (default: 30.0)
-- `stream` (bool, optional): Enable streaming responses (default: False)
-- `selected_outputs` (list[str], optional): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
-- `async_execution` (bool, optional): Execute asynchronously (default: False)
-
-**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
-
-When `async_execution=True`, returns immediately with a task ID for polling. Otherwise, waits for completion.
-
-##### get_workflow_status()
-
-Get the status of a workflow (deployment status, etc.).
-
-```python
-status = client.get_workflow_status("workflow-id")
-print("Is deployed:", status.is_deployed)
-```
-
-**Parameters:**
-- `workflow_id` (str): The ID of the workflow
-
-**Returns:** `WorkflowStatus`
-
-##### validate_workflow()
-
-Validate that a workflow is ready for execution.
-
-```python
-is_ready = client.validate_workflow("workflow-id")
-if is_ready:
- # Workflow is deployed and ready
- pass
-```
-
-**Parameters:**
-- `workflow_id` (str): The ID of the workflow
-
-**Returns:** `bool`
-
-##### get_job_status()
-
-Get the status of an async job execution.
-
-```python
-status = client.get_job_status("task-id-from-async-execution")
-print("Status:", status["status"]) # 'queued', 'processing', 'completed', 'failed'
-if status["status"] == "completed":
- print("Output:", status["output"])
-```
-
-**Parameters:**
-- `task_id` (str): The task ID returned from async execution
-
-**Returns:** `Dict[str, Any]`
-
-**Response fields:**
-- `success` (bool): Whether the request was successful
-- `taskId` (str): The task ID
-- `status` (str): One of `'queued'`, `'processing'`, `'completed'`, `'failed'`, `'cancelled'`
-- `metadata` (dict): Contains `startedAt`, `completedAt`, and `duration`
-- `output` (any, optional): The workflow output (when completed)
-- `error` (any, optional): Error details (when failed)
-- `estimatedDuration` (int, optional): Estimated duration in milliseconds (when processing/queued)
-
-##### execute_with_retry()
-
-Execute a workflow with automatic retry on rate limit errors using exponential backoff.
-
-```python
-result = client.execute_with_retry(
- "workflow-id",
- input={"message": "Hello"},
- timeout=30.0,
- max_retries=3, # Maximum number of retries
- initial_delay=1.0, # Initial delay in seconds
- max_delay=30.0, # Maximum delay in seconds
- backoff_multiplier=2.0 # Exponential backoff multiplier
-)
-```
-
-**Parameters:**
-- `workflow_id` (str): The ID of the workflow to execute
-- `input` (dict, optional): Input data to pass to the workflow
-- `timeout` (float, optional): Timeout in seconds
-- `stream` (bool, optional): Enable streaming responses
-- `selected_outputs` (list, optional): Block outputs to stream
-- `async_execution` (bool, optional): Execute asynchronously
-- `max_retries` (int, optional): Maximum number of retries (default: 3)
-- `initial_delay` (float, optional): Initial delay in seconds (default: 1.0)
-- `max_delay` (float, optional): Maximum delay in seconds (default: 30.0)
-- `backoff_multiplier` (float, optional): Backoff multiplier (default: 2.0)
-
-**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
-
-The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
-
-##### get_rate_limit_info()
-
-Get the current rate limit information from the last API response.
-
-```python
-rate_limit_info = client.get_rate_limit_info()
-if rate_limit_info:
- print("Limit:", rate_limit_info.limit)
- print("Remaining:", rate_limit_info.remaining)
- print("Reset:", datetime.fromtimestamp(rate_limit_info.reset))
-```
-
-**Returns:** `RateLimitInfo | None`
-
-##### get_usage_limits()
-
-Get current usage limits and quota information for your account.
-
-```python
-limits = client.get_usage_limits()
-print("Sync requests remaining:", limits.rate_limit["sync"]["remaining"])
-print("Async requests remaining:", limits.rate_limit["async"]["remaining"])
-print("Current period cost:", limits.usage["currentPeriodCost"])
-print("Plan:", limits.usage["plan"])
-```
-
-**Returns:** `UsageLimits`
-
-**Response structure:**
-```python
-{
- "success": bool,
- "rateLimit": {
- "sync": {
- "isLimited": bool,
- "limit": int,
- "remaining": int,
- "resetAt": str
- },
- "async": {
- "isLimited": bool,
- "limit": int,
- "remaining": int,
- "resetAt": str
- },
- "authType": str # 'api' or 'manual'
- },
- "usage": {
- "currentPeriodCost": float,
- "limit": float,
- "plan": str # e.g., 'free', 'pro'
- }
-}
-```
-
-##### set_api_key()
-
-Update the API key.
-
-```python
-client.set_api_key("new-api-key")
-```
-
-##### set_base_url()
-
-Update the base URL.
-
-```python
-client.set_base_url("https://my-custom-domain.com")
-```
-
-##### close()
-
-Close the underlying HTTP session.
-
-```python
-client.close()
-```
-
-## Data Classes
-
-### WorkflowExecutionResult
-
-```python
-@dataclass
-class WorkflowExecutionResult:
- success: bool
- output: Optional[Any] = None
- error: Optional[str] = None
- logs: Optional[List[Any]] = None
- metadata: Optional[Dict[str, Any]] = None
- trace_spans: Optional[List[Any]] = None
- total_duration: Optional[float] = None
-```
-
-### AsyncExecutionResult
-
-```python
-@dataclass
-class AsyncExecutionResult:
- success: bool
- task_id: str
- status: str # 'queued'
- created_at: str
- links: Dict[str, str] # e.g., {"status": "/api/jobs/{taskId}"}
-```
-
-### WorkflowStatus
-
-```python
-@dataclass
-class WorkflowStatus:
- is_deployed: bool
- deployed_at: Optional[str] = None
- needs_redeployment: bool = False
-```
-
-### RateLimitInfo
-
-```python
-@dataclass
-class RateLimitInfo:
- limit: int
- remaining: int
- reset: int
- retry_after: Optional[int] = None
-```
-
-### UsageLimits
-
-```python
-@dataclass
-class UsageLimits:
- success: bool
- rate_limit: Dict[str, Any]
- usage: Dict[str, Any]
-```
-
-### SimStudioError
-
-```python
-class SimStudioError(Exception):
- def __init__(self, message: str, code: Optional[str] = None, status: Optional[int] = None):
- super().__init__(message)
- self.code = code
- self.status = status
-```
-
-**Common error codes:**
-- `UNAUTHORIZED`: Invalid API key
-- `TIMEOUT`: Request timed out
-- `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
-- `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
-- `EXECUTION_ERROR`: Workflow execution failed
-
-## Examples
-
-### Basic Workflow Execution
-
-
-
- Set up the SimStudioClient with your API key.
-
-
- Check if the workflow is deployed and ready for execution.
-
-
- Run the workflow with your input data.
-
-
- Process the execution result and handle any errors.
-
-
-
-```python
-import os
-from simstudio import SimStudioClient
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def run_workflow():
- try:
- # Check if workflow is ready
- is_ready = client.validate_workflow("my-workflow-id")
- if not is_ready:
- raise Exception("Workflow is not deployed or ready")
-
- # Execute the workflow
- result = client.execute_workflow(
- "my-workflow-id",
- input={
- "message": "Process this data",
- "user_id": "12345"
- }
- )
-
- if result.success:
- print("Output:", result.output)
- print("Duration:", result.metadata.get("duration") if result.metadata else None)
- else:
- print("Workflow failed:", result.error)
-
- except Exception as error:
- print("Error:", error)
-
-run_workflow()
-```
-
-### Error Handling
-
-Handle different types of errors that may occur during workflow execution:
-
-```python
-from simstudio import SimStudioClient, SimStudioError
-import os
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def execute_with_error_handling():
- try:
- result = client.execute_workflow("workflow-id")
- return result
- except SimStudioError as error:
- if error.code == "UNAUTHORIZED":
- print("Invalid API key")
- elif error.code == "TIMEOUT":
- print("Workflow execution timed out")
- elif error.code == "USAGE_LIMIT_EXCEEDED":
- print("Usage limit exceeded")
- elif error.code == "INVALID_JSON":
- print("Invalid JSON in request body")
- else:
- print(f"Workflow error: {error}")
- raise
- except Exception as error:
- print(f"Unexpected error: {error}")
- raise
-```
-
-### Context Manager Usage
-
-Use the client as a context manager to automatically handle resource cleanup:
-
-```python
-from simstudio import SimStudioClient
-import os
-
-# Using context manager to automatically close the session
-with SimStudioClient(api_key=os.getenv("SIM_API_KEY")) as client:
- result = client.execute_workflow("workflow-id")
- print("Result:", result)
-# Session is automatically closed here
-```
-
-### Batch Workflow Execution
-
-Execute multiple workflows efficiently:
-
-```python
-from simstudio import SimStudioClient
-import os
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def execute_workflows_batch(workflow_data_pairs):
- """Execute multiple workflows with different input data."""
- results = []
-
- for workflow_id, input_data in workflow_data_pairs:
- try:
- # Validate workflow before execution
- if not client.validate_workflow(workflow_id):
- print(f"Skipping {workflow_id}: not deployed")
- continue
-
- result = client.execute_workflow(workflow_id, input_data)
- results.append({
- "workflow_id": workflow_id,
- "success": result.success,
- "output": result.output,
- "error": result.error
- })
-
- except Exception as error:
- results.append({
- "workflow_id": workflow_id,
- "success": False,
- "error": str(error)
- })
-
- return results
-
-# Example usage
-workflows = [
- ("workflow-1", {"type": "analysis", "data": "sample1"}),
- ("workflow-2", {"type": "processing", "data": "sample2"}),
-]
-
-results = execute_workflows_batch(workflows)
-for result in results:
- print(f"Workflow {result['workflow_id']}: {'Success' if result['success'] else 'Failed'}")
-```
-
-### Async Workflow Execution
-
-Execute workflows asynchronously for long-running tasks:
-
-```python
-import os
-import time
-from simstudio import SimStudioClient
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def execute_async():
- try:
- # Start async execution
- result = client.execute_workflow(
- "workflow-id",
- input={"data": "large dataset"},
- async_execution=True # Execute asynchronously
- )
-
- # Check if result is an async execution
- if hasattr(result, 'task_id'):
- print(f"Task ID: {result.task_id}")
- print(f"Status endpoint: {result.links['status']}")
-
- # Poll for completion
- status = client.get_job_status(result.task_id)
-
- while status["status"] in ["queued", "processing"]:
- print(f"Current status: {status['status']}")
- time.sleep(2) # Wait 2 seconds
- status = client.get_job_status(result.task_id)
-
- if status["status"] == "completed":
- print("Workflow completed!")
- print(f"Output: {status['output']}")
- print(f"Duration: {status['metadata']['duration']}")
- else:
- print(f"Workflow failed: {status['error']}")
-
- except Exception as error:
- print(f"Error: {error}")
-
-execute_async()
-```
-
-### Rate Limiting and Retry
-
-Handle rate limits automatically with exponential backoff:
-
-```python
-import os
-from simstudio import SimStudioClient, SimStudioError
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def execute_with_retry_handling():
- try:
- # Automatically retries on rate limit
- result = client.execute_with_retry(
- "workflow-id",
- input={"message": "Process this"},
- max_retries=5,
- initial_delay=1.0,
- max_delay=60.0,
- backoff_multiplier=2.0
- )
-
- print(f"Success: {result}")
- except SimStudioError as error:
- if error.code == "RATE_LIMIT_EXCEEDED":
- print("Rate limit exceeded after all retries")
-
- # Check rate limit info
- rate_limit_info = client.get_rate_limit_info()
- if rate_limit_info:
- from datetime import datetime
- reset_time = datetime.fromtimestamp(rate_limit_info.reset)
- print(f"Rate limit resets at: {reset_time}")
-
-execute_with_retry_handling()
-```
-
-### Usage Monitoring
-
-Monitor your account usage and limits:
-
-```python
-import os
-from simstudio import SimStudioClient
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def check_usage():
- try:
- limits = client.get_usage_limits()
-
- print("=== Rate Limits ===")
- print("Sync requests:")
- print(f" Limit: {limits.rate_limit['sync']['limit']}")
- print(f" Remaining: {limits.rate_limit['sync']['remaining']}")
- print(f" Resets at: {limits.rate_limit['sync']['resetAt']}")
- print(f" Is limited: {limits.rate_limit['sync']['isLimited']}")
-
- print("\nAsync requests:")
- print(f" Limit: {limits.rate_limit['async']['limit']}")
- print(f" Remaining: {limits.rate_limit['async']['remaining']}")
- print(f" Resets at: {limits.rate_limit['async']['resetAt']}")
- print(f" Is limited: {limits.rate_limit['async']['isLimited']}")
-
- print("\n=== Usage ===")
- print(f"Current period cost: ${limits.usage['currentPeriodCost']:.2f}")
- print(f"Limit: ${limits.usage['limit']:.2f}")
- print(f"Plan: {limits.usage['plan']}")
-
- percent_used = (limits.usage['currentPeriodCost'] / limits.usage['limit']) * 100
- print(f"Usage: {percent_used:.1f}%")
-
- if percent_used > 80:
- print("⚠️ Warning: You are approaching your usage limit!")
-
- except Exception as error:
- print(f"Error checking usage: {error}")
-
-check_usage()
-```
-
-### Streaming Workflow Execution
-
-Execute workflows with real-time streaming responses:
-
-```python
-from simstudio import SimStudioClient
-import os
-
-client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
-
-def execute_with_streaming():
- """Execute workflow with streaming enabled."""
- try:
- # Enable streaming for specific block outputs
- result = client.execute_workflow(
- "workflow-id",
- input={"message": "Count to five"},
- stream=True,
- selected_outputs=["agent1.content"] # Use blockName.attribute format
- )
-
- print("Workflow result:", result)
- except Exception as error:
- print("Error:", error)
-
-execute_with_streaming()
-```
-
-The streaming response follows the Server-Sent Events (SSE) format:
-
-```
-data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
-
-data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
-
-data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
-
-data: [DONE]
-```
-
-**Flask Streaming Example:**
-
-```python
-from flask import Flask, Response, stream_with_context
-import requests
-import json
-import os
-
-app = Flask(__name__)
-
-@app.route('/stream-workflow')
-def stream_workflow():
- """Stream workflow execution to the client."""
-
- def generate():
- response = requests.post(
- 'https://sim.ai/api/workflows/WORKFLOW_ID/execute',
- headers={
- 'Content-Type': 'application/json',
- 'X-API-Key': os.getenv('SIM_API_KEY')
- },
- json={
- 'message': 'Generate a story',
- 'stream': True,
- 'selectedOutputs': ['agent1.content']
- },
- stream=True
- )
-
- for line in response.iter_lines():
- if line:
- decoded_line = line.decode('utf-8')
- if decoded_line.startswith('data: '):
- data = decoded_line[6:] # Remove 'data: ' prefix
-
- if data == '[DONE]':
- break
-
- try:
- parsed = json.loads(data)
- if 'chunk' in parsed:
- yield f"data: {json.dumps(parsed)}\n\n"
- elif parsed.get('event') == 'done':
- yield f"data: {json.dumps(parsed)}\n\n"
- print("Execution complete:", parsed.get('metadata'))
- except json.JSONDecodeError:
- pass
-
- return Response(
- stream_with_context(generate()),
- mimetype='text/event-stream'
- )
-
-if __name__ == '__main__':
- app.run(debug=True)
-```
-
-### Environment Configuration
-
-Configure the client using environment variables:
-
-
-
- ```python
- import os
- from simstudio import SimStudioClient
-
- # Development configuration
- client = SimStudioClient(
- api_key=os.getenv("SIM_API_KEY")
- base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
- )
- ```
-
-
- ```python
- import os
- from simstudio import SimStudioClient
-
- # Production configuration with error handling
- api_key = os.getenv("SIM_API_KEY")
- if not api_key:
- raise ValueError("SIM_API_KEY environment variable is required")
-
- client = SimStudioClient(
- api_key=api_key,
- base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
- )
- ```
-
-
-
-## Getting Your API Key
-
-
-
- Navigate to [Sim](https://sim.ai) and log in to your account.
-
-
- Navigate to the workflow you want to execute programmatically.
-
-
- Click on "Deploy" to deploy your workflow if it hasn't been deployed yet.
-
-
- During the deployment process, select or create an API key.
-
-
- Copy the API key to use in your Python application.
-
-
-
-## Requirements
-
-- Python 3.8+
-- requests >= 2.25.0
-
-## License
-
-Apache-2.0
-
-import { FAQ } from '@/components/ui/faq'
-
-
\ No newline at end of file
diff --git a/apps/docs/content/docs/en/sdks/typescript.mdx b/apps/docs/content/docs/en/sdks/typescript.mdx
deleted file mode 100644
index 476cfb964d4..00000000000
--- a/apps/docs/content/docs/en/sdks/typescript.mdx
+++ /dev/null
@@ -1,1030 +0,0 @@
----
-title: TypeScript
----
-
-import { Callout } from 'fumadocs-ui/components/callout'
-import { Card, Cards } from 'fumadocs-ui/components/card'
-import { Step, Steps } from 'fumadocs-ui/components/steps'
-import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
-
-The official TypeScript/JavaScript SDK for Sim provides full type safety and supports both Node.js and browser environments, allowing you to execute workflows programmatically from your Node.js applications, web applications, and other JavaScript environments.
-
-
- The TypeScript SDK provides full type safety, async execution support, automatic rate limiting with exponential backoff, and usage tracking.
-
-
-## Installation
-
-Install the SDK using your preferred package manager:
-
-
-
- ```bash
- npm install simstudio-ts-sdk
- ```
-
-
- ```bash
- yarn add simstudio-ts-sdk
- ```
-
-
- ```bash
- bun add simstudio-ts-sdk
- ```
-
-
-
-## Quick Start
-
-Here's a simple example to get you started:
-
-```typescript
-import { SimStudioClient } from 'simstudio-ts-sdk';
-
-// Initialize the client
-const client = new SimStudioClient({
- apiKey: 'your-api-key-here',
- baseUrl: 'https://sim.ai' // optional, defaults to https://sim.ai
-});
-
-// Execute a workflow
-try {
- const result = await client.executeWorkflow('workflow-id');
- console.log('Workflow executed successfully:', result);
-} catch (error) {
- console.error('Workflow execution failed:', error);
-}
-```
-
-## API Reference
-
-### SimStudioClient
-
-#### Constructor
-
-```typescript
-new SimStudioClient(config: SimStudioConfig)
-```
-
-**Configuration:**
-- `config.apiKey` (string): Your Sim API key
-- `config.baseUrl` (string, optional): Base URL for the Sim API (defaults to `https://sim.ai`)
-
-#### Methods
-
-##### executeWorkflow()
-
-Execute a workflow with optional input data.
-
-```typescript
-const result = await client.executeWorkflow('workflow-id', { message: 'Hello, world!' }, {
- timeout: 30000 // 30 seconds
-});
-```
-
-**Parameters:**
-- `workflowId` (string): The ID of the workflow to execute
-- `input` (any, optional): Input data to pass to the workflow
-- `options` (ExecutionOptions, optional):
- - `timeout` (number): Timeout in milliseconds (default: 30000)
- - `stream` (boolean): Enable streaming responses (default: false)
- - `selectedOutputs` (string[]): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
- - `async` (boolean): Execute asynchronously (default: false)
-
-**Returns:** `Promise`
-
-When `async: true`, returns immediately with a task ID for polling. Otherwise, waits for completion.
-
-##### getWorkflowStatus()
-
-Get the status of a workflow (deployment status, etc.).
-
-```typescript
-const status = await client.getWorkflowStatus('workflow-id');
-console.log('Is deployed:', status.isDeployed);
-```
-
-**Parameters:**
-- `workflowId` (string): The ID of the workflow
-
-**Returns:** `Promise`
-
-##### validateWorkflow()
-
-Validate that a workflow is ready for execution.
-
-```typescript
-const isReady = await client.validateWorkflow('workflow-id');
-if (isReady) {
- // Workflow is deployed and ready
-}
-```
-
-**Parameters:**
-- `workflowId` (string): The ID of the workflow
-
-**Returns:** `Promise`
-
-##### getJobStatus()
-
-Get the status of an async job execution.
-
-```typescript
-const status = await client.getJobStatus('task-id-from-async-execution');
-console.log('Status:', status.status); // 'queued', 'processing', 'completed', 'failed'
-if (status.status === 'completed') {
- console.log('Output:', status.output);
-}
-```
-
-**Parameters:**
-- `taskId` (string): The task ID returned from async execution
-
-**Returns:** `Promise`
-
-**Response fields:**
-- `success` (boolean): Whether the request was successful
-- `taskId` (string): The task ID
-- `status` (string): One of `'queued'`, `'processing'`, `'completed'`, `'failed'`, `'cancelled'`
-- `metadata` (object): Contains `startedAt`, `completedAt`, and `duration`
-- `output` (any, optional): The workflow output (when completed)
-- `error` (any, optional): Error details (when failed)
-- `estimatedDuration` (number, optional): Estimated duration in milliseconds (when processing/queued)
-
-##### executeWithRetry()
-
-Execute a workflow with automatic retry on rate limit errors using exponential backoff.
-
-```typescript
-const result = await client.executeWithRetry('workflow-id', { message: 'Hello' }, {
- timeout: 30000
-}, {
- maxRetries: 3, // Maximum number of retries
- initialDelay: 1000, // Initial delay in ms (1 second)
- maxDelay: 30000, // Maximum delay in ms (30 seconds)
- backoffMultiplier: 2 // Exponential backoff multiplier
-});
-```
-
-**Parameters:**
-- `workflowId` (string): The ID of the workflow to execute
-- `input` (any, optional): Input data to pass to the workflow
-- `options` (ExecutionOptions, optional): Same as `executeWorkflow()`
-- `retryOptions` (RetryOptions, optional):
- - `maxRetries` (number): Maximum number of retries (default: 3)
- - `initialDelay` (number): Initial delay in ms (default: 1000)
- - `maxDelay` (number): Maximum delay in ms (default: 30000)
- - `backoffMultiplier` (number): Backoff multiplier (default: 2)
-
-**Returns:** `Promise`
-
-The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
-
-##### getRateLimitInfo()
-
-Get the current rate limit information from the last API response.
-
-```typescript
-const rateLimitInfo = client.getRateLimitInfo();
-if (rateLimitInfo) {
- console.log('Limit:', rateLimitInfo.limit);
- console.log('Remaining:', rateLimitInfo.remaining);
- console.log('Reset:', new Date(rateLimitInfo.reset * 1000));
-}
-```
-
-**Returns:** `RateLimitInfo | null`
-
-##### getUsageLimits()
-
-Get current usage limits and quota information for your account.
-
-```typescript
-const limits = await client.getUsageLimits();
-console.log('Sync requests remaining:', limits.rateLimit.sync.remaining);
-console.log('Async requests remaining:', limits.rateLimit.async.remaining);
-console.log('Current period cost:', limits.usage.currentPeriodCost);
-console.log('Plan:', limits.usage.plan);
-```
-
-**Returns:** `Promise`
-
-**Response structure:**
-```typescript
-{
- success: boolean
- rateLimit: {
- sync: {
- isLimited: boolean
- limit: number
- remaining: number
- resetAt: string
- }
- async: {
- isLimited: boolean
- limit: number
- remaining: number
- resetAt: string
- }
- authType: string // 'api' or 'manual'
- }
- usage: {
- currentPeriodCost: number
- limit: number
- plan: string // e.g., 'free', 'pro'
- }
-}
-```
-
-##### setApiKey()
-
-Update the API key.
-
-```typescript
-client.setApiKey('new-api-key');
-```
-
-##### setBaseUrl()
-
-Update the base URL.
-
-```typescript
-client.setBaseUrl('https://my-custom-domain.com');
-```
-
-## Types
-
-### WorkflowExecutionResult
-
-```typescript
-interface WorkflowExecutionResult {
- success: boolean;
- output?: any;
- error?: string;
- logs?: any[];
- metadata?: {
- duration?: number;
- executionId?: string;
- [key: string]: any;
- };
- traceSpans?: any[];
- totalDuration?: number;
-}
-```
-
-### AsyncExecutionResult
-
-```typescript
-interface AsyncExecutionResult {
- success: boolean;
- taskId: string;
- status: 'queued';
- createdAt: string;
- links: {
- status: string; // e.g., "/api/jobs/{taskId}"
- };
-}
-```
-
-### WorkflowStatus
-
-```typescript
-interface WorkflowStatus {
- isDeployed: boolean;
- deployedAt?: string;
- needsRedeployment: boolean;
-}
-```
-
-### RateLimitInfo
-
-```typescript
-interface RateLimitInfo {
- limit: number;
- remaining: number;
- reset: number;
- retryAfter?: number;
-}
-```
-
-### UsageLimits
-
-```typescript
-interface UsageLimits {
- success: boolean;
- rateLimit: {
- sync: {
- isLimited: boolean;
- limit: number;
- remaining: number;
- resetAt: string;
- };
- async: {
- isLimited: boolean;
- limit: number;
- remaining: number;
- resetAt: string;
- };
- authType: string;
- };
- usage: {
- currentPeriodCost: number;
- limit: number;
- plan: string;
- };
-}
-```
-
-### SimStudioError
-
-```typescript
-class SimStudioError extends Error {
- code?: string;
- status?: number;
-}
-```
-
-**Common error codes:**
-- `UNAUTHORIZED`: Invalid API key
-- `TIMEOUT`: Request timed out
-- `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
-- `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
-- `EXECUTION_ERROR`: Workflow execution failed
-
-## Examples
-
-### Basic Workflow Execution
-
-
-
- Set up the SimStudioClient with your API key.
-
-
- Check if the workflow is deployed and ready for execution.
-
-
- Run the workflow with your input data.
-
-
- Process the execution result and handle any errors.
-
-
-
-```typescript
-import { SimStudioClient } from 'simstudio-ts-sdk';
-
-const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
-});
-
-async function runWorkflow() {
- try {
- // Check if workflow is ready
- const isReady = await client.validateWorkflow('my-workflow-id');
- if (!isReady) {
- throw new Error('Workflow is not deployed or ready');
- }
-
- // Execute the workflow
- const result = await client.executeWorkflow('my-workflow-id', {
- message: 'Process this data',
- userId: '12345'
- });
-
- if (result.success) {
- console.log('Output:', result.output);
- console.log('Duration:', result.metadata?.duration);
- } else {
- console.error('Workflow failed:', result.error);
- }
- } catch (error) {
- console.error('Error:', error);
- }
-}
-
-runWorkflow();
-```
-
-### Error Handling
-
-Handle different types of errors that may occur during workflow execution:
-
-```typescript
-import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
-
-const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
-});
-
-async function executeWithErrorHandling() {
- try {
- const result = await client.executeWorkflow('workflow-id');
- return result;
- } catch (error) {
- if (error instanceof SimStudioError) {
- switch (error.code) {
- case 'UNAUTHORIZED':
- console.error('Invalid API key');
- break;
- case 'TIMEOUT':
- console.error('Workflow execution timed out');
- break;
- case 'USAGE_LIMIT_EXCEEDED':
- console.error('Usage limit exceeded');
- break;
- case 'INVALID_JSON':
- console.error('Invalid JSON in request body');
- break;
- default:
- console.error('Workflow error:', error.message);
- }
- } else {
- console.error('Unexpected error:', error);
- }
- throw error;
- }
-}
-```
-
-### Environment Configuration
-
-Configure the client using environment variables:
-
-
-
- ```typescript
- import { SimStudioClient } from 'simstudio-ts-sdk';
-
- // Development configuration
- const apiKey = process.env.SIM_API_KEY;
- if (!apiKey) {
- throw new Error('SIM_API_KEY environment variable is required');
- }
-
- const client = new SimStudioClient({
- apiKey,
- baseUrl: process.env.SIM_BASE_URL // optional
- });
- ```
-
-
- ```typescript
- import { SimStudioClient } from 'simstudio-ts-sdk';
-
- // Production configuration with validation
- const apiKey = process.env.SIM_API_KEY;
- if (!apiKey) {
- throw new Error('SIM_API_KEY environment variable is required');
- }
-
- const client = new SimStudioClient({
- apiKey,
- baseUrl: process.env.SIM_BASE_URL || 'https://sim.ai'
- });
- ```
-
-
-
-### Node.js Express Integration
-
-Integrate with an Express.js server:
-
-```typescript
-import express from 'express';
-import { SimStudioClient } from 'simstudio-ts-sdk';
-
-const app = express();
-const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
-});
-
-app.use(express.json());
-
-app.post('/execute-workflow', async (req, res) => {
- try {
- const { workflowId, input } = req.body;
-
- const result = await client.executeWorkflow(workflowId, input, {
- timeout: 60000
- });
-
- res.json({
- success: true,
- data: result
- });
- } catch (error) {
- console.error('Workflow execution error:', error);
- res.status(500).json({
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- });
- }
-});
-
-app.listen(3000, () => {
- console.log('Server running on port 3000');
-});
-```
-
-### Next.js API Route
-
-Use with Next.js API routes:
-
-```typescript
-// pages/api/workflow.ts or app/api/workflow/route.ts
-import { NextApiRequest, NextApiResponse } from 'next';
-import { SimStudioClient } from 'simstudio-ts-sdk';
-
-const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
-});
-
-export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse
-) {
- if (req.method !== 'POST') {
- return res.status(405).json({ error: 'Method not allowed' });
- }
-
- try {
- const { workflowId, input } = req.body;
-
- const result = await client.executeWorkflow(workflowId, input, {
- timeout: 30000
- });
-
- res.status(200).json(result);
- } catch (error) {
- console.error('Error executing workflow:', error);
- res.status(500).json({
- error: 'Failed to execute workflow'
- });
- }
-}
-```
-
-### Browser Usage
-
-Use in the browser (with proper CORS configuration):
-
-```typescript
-import { SimStudioClient } from 'simstudio-ts-sdk';
-
-// Note: In production, use a proxy server to avoid exposing API keys
-const client = new SimStudioClient({
- apiKey: 'your-public-api-key', // Use with caution in browser
- baseUrl: 'https://sim.ai'
-});
-
-async function executeClientSideWorkflow() {
- try {
- const result = await client.executeWorkflow('workflow-id', {
- userInput: 'Hello from browser'
- });
-
- console.log('Workflow result:', result);
-
- // Update UI with result
- document.getElementById('result')!.textContent =
- JSON.stringify(result.output, null, 2);
- } catch (error) {
- console.error('Error:', error);
- }
-}
-```
-
-### File Upload
-
-File objects are automatically detected and converted to base64 format. Include them in your input under the field name matching your workflow's API trigger input format.
-
-The SDK converts File objects to this format:
-```typescript
-{
- type: 'file',
- data: 'data:mime/type;base64,base64data',
- name: 'filename',
- mime: 'mime/type'
-}
-```
-
-Alternatively, you can manually provide files using the URL format:
-```typescript
-{
- type: 'url',
- data: 'https://example.com/file.pdf',
- name: 'file.pdf',
- mime: 'application/pdf'
-}
-```
-
-
-
- ```typescript
- import { SimStudioClient } from 'simstudio-ts-sdk';
-
- const client = new SimStudioClient({
- apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY!
- });
-
- // From file input
- async function handleFileUpload(event: Event) {
- const input = event.target as HTMLInputElement;
- const files = Array.from(input.files || []);
-
- // Include files under the field name from your API trigger's input format
- const result = await client.executeWorkflow('workflow-id', {
- documents: files, // Must match your workflow's "files" field name
- instructions: 'Analyze these documents'
- });
-
- console.log('Result:', result);
- }
- ```
-
-
- ```typescript
- import { SimStudioClient } from 'simstudio-ts-sdk';
- import fs from 'fs';
-
- const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
- });
-
- // Read file and create File object
- const fileBuffer = fs.readFileSync('./document.pdf');
- const file = new File([fileBuffer], 'document.pdf', {
- type: 'application/pdf'
- });
-
- // Include files under the field name from your API trigger's input format
- const result = await client.executeWorkflow('workflow-id', {
- documents: [file], // Must match your workflow's "files" field name
- query: 'Summarize this document'
- });
- ```
-
-
-
-
- When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions.
-
-
-### React Hook Example
-
-Create a custom React hook for workflow execution:
-
-```typescript
-import { useState, useCallback } from 'react';
-import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk';
-
-const client = new SimStudioClient({
- apiKey: process.env.SIM_API_KEY!
-});
-
-interface UseWorkflowResult {
- result: WorkflowExecutionResult | null;
- loading: boolean;
- error: Error | null;
- executeWorkflow: (workflowId: string, input?: any) => Promise;
-}
-
-export function useWorkflow(): UseWorkflowResult {
- const [result, setResult] = useState(null);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState(null);
-
- const executeWorkflow = useCallback(async (workflowId: string, input?: any) => {
- setLoading(true);
- setError(null);
- setResult(null);
-
- try {
- const workflowResult = await client.executeWorkflow(workflowId, input, {
- timeout: 30000
- });
- setResult(workflowResult);
- } catch (err) {
- setError(err instanceof Error ? err : new Error('Unknown error'));
- } finally {
- setLoading(false);
- }
- }, []);
-
- return {
- result,
- loading,
- error,
- executeWorkflow
- };
-}
-
-// Usage in component
-function WorkflowComponent() {
- const { result, loading, error, executeWorkflow } = useWorkflow();
-
- const handleExecute = () => {
- executeWorkflow('my-workflow-id', {
- message: 'Hello from React!'
- });
- };
-
- return (
-