Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions apps/docs/content/docs/de/api-reference/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,22 @@ curl -X POST https://www.sim.ai/api/workflows/{workflowId}/execute \
-d '{"inputs": {}, "async": true}'
```

This returns immediately with a `taskId`:
This returns immediately with a `jobId` and `statusUrl`:

```json
{
"success": true,
"taskId": "job_abc123",
"status": "queued"
"jobId": "job_abc123",
"statusUrl": "https://www.sim.ai/api/jobs/job_abc123",
"message": "Workflow execution started",
"async": true
}
```

Poll the [Get Job Status](/api-reference/workflows/getJobStatus) endpoint until the status is `completed` or `failed`:

```bash
curl https://www.sim.ai/api/jobs/{taskId} \
curl https://www.sim.ai/api/jobs/{jobId} \
-H "X-API-Key: YOUR_API_KEY"
```

Expand Down
10 changes: 6 additions & 4 deletions apps/docs/content/docs/en/api-reference/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,22 @@ curl -X POST https://www.sim.ai/api/workflows/{workflowId}/execute \
-d '{"inputs": {}, "async": true}'
```

This returns immediately with a `taskId`:
This returns immediately with a `jobId` and `statusUrl`:

```json
{
"success": true,
"taskId": "job_abc123",
"status": "queued"
"jobId": "job_abc123",
"statusUrl": "https://www.sim.ai/api/jobs/job_abc123",
"message": "Workflow execution started",
"async": true
}
```

Poll the [Get Job Status](/api-reference/workflows/getJobStatus) endpoint until the status is `completed` or `failed`:

```bash
curl https://www.sim.ai/api/jobs/{taskId} \
curl https://www.sim.ai/api/jobs/{jobId} \
-H "X-API-Key: YOUR_API_KEY"
```

Expand Down
29 changes: 15 additions & 14 deletions apps/docs/content/docs/en/api-reference/python.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ result = client.execute_workflow(

**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`

When `async_execution=True`, returns immediately with a task ID for polling. Otherwise, waits for completion.
When `async_execution=True`, returns immediately with a `job_id` and `status_url` for polling. Otherwise, waits for completion.

##### get_workflow_status()

Expand Down Expand Up @@ -117,20 +117,20 @@ if is_ready:
Get the status of an async job execution.

```python
status = client.get_job_status("task-id-from-async-execution")
status = client.get_job_status("job-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
- `task_id` (str): The job ID returned from async execution

**Returns:** `Dict[str, Any]`

**Response fields:**
- `success` (bool): Whether the request was successful
- `taskId` (str): The task ID
- `taskId` (str): The job 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)
Expand Down Expand Up @@ -270,10 +270,11 @@ class WorkflowExecutionResult:
@dataclass
class AsyncExecutionResult:
success: bool
task_id: str
status: str # 'queued'
created_at: str
links: Dict[str, str] # e.g., {"status": "/api/jobs/{taskId}"}
job_id: str
status_url: str
execution_id: Optional[str] = None
message: str = ""
async_execution: bool = True
```

### WorkflowStatus
Expand Down Expand Up @@ -493,17 +494,17 @@ def execute_async():
)

# 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']}")
if hasattr(result, 'job_id'):
print(f"Job ID: {result.job_id}")
print(f"Status endpoint: {result.status_url}")

# Poll for completion
status = client.get_job_status(result.task_id)
status = client.get_job_status(result.job_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)
status = client.get_job_status(result.job_id)

if status["status"] == "completed":
print("Workflow completed!")
Expand Down Expand Up @@ -764,7 +765,7 @@ import { FAQ } from '@/components/ui/faq'

<FAQ items={[
{ question: "Do I need to deploy a workflow before I can execute it via the SDK?", answer: "Yes. Workflows must be deployed before they can be executed through the SDK. You can use the validate_workflow() method to check whether a workflow is deployed and ready. If it returns False, deploy the workflow from the Sim UI first and create or select an API key during deployment." },
{ question: "What is the difference between sync and async execution?", answer: "Sync execution (the default) blocks until the workflow completes and returns the full result. Async execution (async_execution=True) returns immediately with a task ID that you can poll using get_job_status(). Use async mode for long-running workflows to avoid request timeouts. Async job statuses include queued, processing, completed, failed, and cancelled." },
{ question: "What is the difference between sync and async execution?", answer: "Sync execution (the default) blocks until the workflow completes and returns the full result. Async execution (async_execution=True) returns immediately with a job ID and status URL that you can poll using get_job_status(). Use async mode for long-running workflows to avoid request timeouts. Async job statuses include queued, processing, completed, failed, and cancelled." },
{ question: "How does the SDK handle rate limiting?", answer: "The SDK provides built-in rate limiting support through the execute_with_retry() method. It uses exponential backoff (1s, 2s, 4s, 8s...) with 25% jitter to avoid thundering herd problems. If the API returns a retry-after header, that value is used instead. You can configure max_retries, initial_delay, max_delay, and backoff_multiplier. Use get_rate_limit_info() to check your current rate limit status." },
{ question: "Can I use the Python SDK as a context manager?", answer: "Yes. The SimStudioClient supports Python's context manager protocol. Use it with the 'with' statement to automatically close the underlying HTTP session when you are done, which is especially useful for scripts that create and discard client instances." },
{ question: "How do I handle different types of errors from the SDK?", answer: "The SDK raises SimStudioError with a code property for API-specific errors. Common error codes are UNAUTHORIZED (invalid API key), TIMEOUT (request timed out), RATE_LIMIT_EXCEEDED (too many requests), USAGE_LIMIT_EXCEEDED (billing limit reached), and EXECUTION_ERROR (workflow failed). Use the error code to implement targeted error handling and recovery logic." },
Expand Down
31 changes: 15 additions & 16 deletions apps/docs/content/docs/en/api-reference/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const result = await client.executeWorkflow('workflow-id', { message: 'Hello, wo

**Returns:** `Promise<WorkflowExecutionResult | AsyncExecutionResult>`

When `async: true`, returns immediately with a task ID for polling. Otherwise, waits for completion.
When `async: true`, returns immediately with a `jobId` and `statusUrl` for polling. Otherwise, waits for completion.

##### getWorkflowStatus()

Expand Down Expand Up @@ -131,21 +131,21 @@ if (isReady) {
Get the status of an async job execution.

```typescript
const status = await client.getJobStatus('task-id-from-async-execution');
const status = await client.getJobStatus('job-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
- `jobId` (string): The job ID returned from async execution

**Returns:** `Promise<JobStatus>`

**Response fields:**
- `success` (boolean): Whether the request was successful
- `taskId` (string): The task ID
- `taskId` (string): The job 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)
Expand Down Expand Up @@ -278,12 +278,11 @@ interface WorkflowExecutionResult {
```typescript
interface AsyncExecutionResult {
success: boolean;
taskId: string;
status: 'queued';
createdAt: string;
links: {
status: string; // e.g., "/api/jobs/{taskId}"
};
jobId: string;
statusUrl: string;
executionId?: string;
message: string;
async: true;
}
```

Expand Down Expand Up @@ -767,17 +766,17 @@ async function executeAsync() {
});

// Check if result is an async execution
if ('taskId' in result) {
console.log('Task ID:', result.taskId);
console.log('Status endpoint:', result.links.status);
if ('jobId' in result) {
console.log('Job ID:', result.jobId);
console.log('Status endpoint:', result.statusUrl);

// Poll for completion
let status = await client.getJobStatus(result.taskId);
let status = await client.getJobStatus(result.jobId);

while (status.status === 'queued' || status.status === 'processing') {
console.log('Current status:', status.status);
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
status = await client.getJobStatus(result.taskId);
status = await client.getJobStatus(result.jobId);
}

if (status.status === 'completed') {
Expand Down Expand Up @@ -1022,7 +1021,7 @@ import { FAQ } from '@/components/ui/faq'

<FAQ items={[
{ question: "Do I need to deploy a workflow before I can execute it via the SDK?", answer: "Yes. Workflows must be deployed before they can be executed through the SDK. You can use the validateWorkflow() method to check whether a workflow is deployed and ready. If it returns false, deploy the workflow from the Sim UI first and create or select an API key during deployment." },
{ question: "What is the difference between sync and async execution?", answer: "Sync execution (the default) blocks until the workflow completes and returns the full result. Async execution returns immediately with a task ID that you can poll using getJobStatus(). Use async mode for long-running workflows to avoid request timeouts. Async job statuses include queued, processing, completed, failed, and cancelled." },
{ question: "What is the difference between sync and async execution?", answer: "Sync execution (the default) blocks until the workflow completes and returns the full result. Async execution returns immediately with a job ID and status URL that you can poll using getJobStatus(). Use async mode for long-running workflows to avoid request timeouts. Async job statuses include queued, processing, completed, failed, and cancelled." },
{ question: "How does streaming work with the SDK?", answer: "Enable streaming by setting stream: true and specifying selectedOutputs with block names and attributes in blockName.attribute format (e.g., ['agent1.content']). The response uses Server-Sent Events (SSE) format, sending incremental chunks as the workflow executes. Each chunk includes the blockId and the text content. A final done event includes the execution metadata." },
{ question: "How does the SDK handle rate limiting?", answer: "The SDK provides built-in rate limiting support through the executeWithRetry() method. It uses exponential backoff (1s, 2s, 4s, 8s...) with 25% jitter to avoid thundering herd problems. If the API returns a retry-after header, that value is used instead. You can configure maxRetries, initialDelay, maxDelay, and backoffMultiplier. Use getRateLimitInfo() to check your current rate limit status." },
{ question: "Is it safe to use the SDK in browser-side code?", answer: "You can use the SDK in the browser, but you should not expose your API key in client-side code. In production, use a backend proxy server to handle SDK calls, or use a public API key with limited permissions. The SDK works with both Node.js and browser environments, but sensitive keys should stay server-side." },
Expand Down
47 changes: 47 additions & 0 deletions apps/docs/content/docs/en/blocks/function.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,53 @@ plt.show()

## Best Practices

### Large Inputs and Payload Limits

Function blocks receive their code, parameters, resolved references, and previous block context in an internal execution request. Sim can safely reference oversized workflow outputs, such as large `loop.results` or `parallel.results`, when you select a smaller nested field like `<loop.results[0][0].id>`. Larger values are stored in execution storage and passed around as small references until code explicitly reads them.

File outputs are metadata-first by default. Referencing `<file.name>`, `<file.url>`, or similar metadata does not hydrate file contents. In JavaScript functions without imports, a direct base64 reference like `<readfile.file.base64>` is automatically rewritten to a lazy server-side read so the base64 string does not cross the Function request body.

You can also call the helper explicitly:

```javascript
const file = <readfile.file>;
const base64 = await sim.files.readBase64(file);
```

`sim.files.readBase64(file)`, `sim.files.readText(file)`, `sim.files.readBase64Chunk(file, { offset, length })`, and `sim.files.readTextChunk(file, { offset, length })` read from server-side execution storage under memory caps. `sim.values.read(ref)` can explicitly read a large execution value reference. These helpers are available only in JavaScript functions without imports. JavaScript with imports, Python, and shell do not support these lazy helpers yet.

Very large full reads can still fail by design; use chunk helpers or return a file when you need to handle more data.

Use text chunks for text-like files such as logs, CSV, JSONL, and markdown:

```javascript
const file = <readfile.file>;
const firstMegabyte = await sim.files.readTextChunk(file, {
offset: 0,
length: 1024 * 1024,
});

return firstMegabyte.split('\n').slice(0, 10);
```

Use base64 chunks for binary files such as images, PDFs, audio, archives, or APIs that expect base64 input:

```javascript
const file = <readfile.file>;
const firstMegabyteBase64 = await sim.files.readBase64Chunk(file, {
offset: 0,
length: 1024 * 1024,
});

return { name: file.name, chunk: firstMegabyteBase64 };
```

Chunk `offset` and `length` are byte-based. For Unicode text, a chunk can split a multi-byte character at the boundary; use text chunks for approximate text processing and prefer smaller structured references when exact parsing matters.

Avoid passing a full large object into a Function block when you only need one field. For example, prefer `<api.data.customerId>` over `<api.data>` when the API response is large. If a JavaScript Function without imports references a large execution value, Sim automatically reads it through `sim.values.read(...)` at runtime under memory caps.

For large generated data, write the result to a file or table with `outputPath`, `outputSandboxPath`, or `outputTable` instead of returning the entire payload inline.

- **Keep functions focused**: Write functions that do one thing well to improve maintainability and debugging
- **Handle errors gracefully**: Use try/catch blocks to handle potential errors and provide meaningful error messages
- **Test edge cases**: Ensure your code handles unusual inputs, null values, and boundary conditions correctly
Expand Down
14 changes: 12 additions & 2 deletions apps/docs/content/docs/en/blocks/parallel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Choose between two types of parallel execution:
</div>

Use this when you need to run the same operation multiple times concurrently.
If the total count is larger than the batch size, Sim runs the work in serial batches while preserving the original result order.

```
Example: Run 5 parallel instances
Expand All @@ -57,7 +58,7 @@ Choose between two types of parallel execution:
/>
</div>

Each instance processes one item from the collection simultaneously.
Each instance processes one item from the collection. Large collections run in serial batches while preserving each item's original index.

```
Example: Process ["task1", "task2", "task3"] in parallel
Expand Down Expand Up @@ -140,6 +141,12 @@ const allResults = <processtasks.results>;
// Returns: [result1, result2, result3, ...]
```

For large result sets, reference only the entry or field you need, such as `<processtasks.results[10][0].id>`. Sim keeps aggregate results indexable by storing oversized entries in execution storage and hydrating them only when an indexed server-side path is explicitly referenced.

### Batch Size

Parallel blocks run up to 20 branches at a time by default. Increase the total count or collection size to process more work; Sim will execute the next batch after the current batch finishes. You can lower the batch size to reduce concurrency for rate-limited APIs.

### Instance Isolation

Each parallel instance runs independently:
Expand All @@ -157,7 +164,7 @@ Each parallel instance runs independently:
While parallel execution is faster, be mindful of:
- API rate limits when making concurrent requests
- Memory usage with large datasets
- Maximum of 20 concurrent instances to prevent resource exhaustion
- Maximum of 20 concurrent instances per batch to prevent resource exhaustion
</Callout>

## Parallel vs Loop
Expand Down Expand Up @@ -186,6 +193,9 @@ Understanding when to use each:
<li>
<strong>Collection</strong>: Array or object to distribute (collection-based)
</li>
<li>
<strong>Batch size</strong>: Number of branches to run concurrently, from 1 to 20
</li>
</ul>
</Tab>
<Tab>
Expand Down
19 changes: 19 additions & 0 deletions apps/docs/content/docs/en/execution/api-deployment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,25 @@ while (true) {
</Tab>
</Tabs>

#### Oversized outputs

Workflow execution responses are capped by platform request and response limits. When an internal output, log field, streamed field, or async status payload contains a value that is too large to inline, Sim may replace that nested value with a versioned reference:

```json
{
"__simLargeValueRef": true,
"version": 1,
"id": "lv_abc123DEF456",
"kind": "array",
"size": 12582912,
"key": "execution/workspace-id/workflow-id/exec_xyz/large-value-lv_abc123DEF456.json",
"executionId": "exec_xyz",
"preview": { "length": 25000 }
}
```

The `version` field is part of the external API contract. Treat the reference as an opaque placeholder for a value that could not be safely embedded in the response. `id`, `key`, and `executionId` are not fetch URLs; `key` points to execution-scoped server storage. Use `selectedOutputs` to request a smaller nested field, reduce the data passed between blocks, or return the data from a Response block when your workflow intentionally owns the HTTP response body. File outputs are metadata-first; request `.base64` only when you need inline file content. JavaScript Function blocks can explicitly read large files or value refs with the `sim.files` and `sim.values` helpers under memory caps.

### Asynchronous

For long-running workflows, async mode returns a job ID immediately so you don't need to hold the connection open. Add the `X-Execution-Mode: async` header to your request. The API returns HTTP 202 with a job ID and status URL. Poll the status URL until the job completes.
Expand Down
10 changes: 6 additions & 4 deletions apps/docs/content/docs/es/api-reference/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,22 @@ curl -X POST https://www.sim.ai/api/workflows/{workflowId}/execute \
-d '{"inputs": {}, "async": true}'
```

This returns immediately with a `taskId`:
This returns immediately with a `jobId` and `statusUrl`:

```json
{
"success": true,
"taskId": "job_abc123",
"status": "queued"
"jobId": "job_abc123",
"statusUrl": "https://www.sim.ai/api/jobs/job_abc123",
"message": "Workflow execution started",
"async": true
}
```

Poll the [Get Job Status](/api-reference/workflows/getJobStatus) endpoint until the status is `completed` or `failed`:

```bash
curl https://www.sim.ai/api/jobs/{taskId} \
curl https://www.sim.ai/api/jobs/{jobId} \
-H "X-API-Key: YOUR_API_KEY"
```

Expand Down
Loading
Loading