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
6 changes: 3 additions & 3 deletions docs/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
title: Introduction
description: Run AI agents (Claude Code, OpenAI Agents, and more) in any sandbox, controlled from Python over WebSocket.
description: Run AI agents (Claude Code, OpenAI Agents, and more) in any sandbox, controlled from Python or TypeScript over WebSocket.
---

[RuntimeUse](https://github.com/getlark/runtimeuse) is an open-source runtime and client library for running AI agents inside isolated sandboxes and controlling them from Python over WebSocket.
[RuntimeUse](https://github.com/getlark/runtimeuse) is an open-source runtime and client library for running AI agents inside isolated sandboxes and controlling them from Python or TypeScript over WebSocket.


<img src="/terminal.svg" alt="RuntimeUse terminal" style={{ maxWidth: '560px', width: '100%' }} />
Expand All @@ -25,7 +25,7 @@ description: Run AI agents (Claude Code, OpenAI Agents, and more) in any sandbox
## What it handles

- **Task invocations**: send a prompt to any agent runtime and receive a result over WebSocket as text or typed JSON.
- **pre_agent_downloadables**: fetch code, repos, or data into the sandbox before the run starts.
- **Pre-agent downloadables**: fetch code, repos, or data into the sandbox before the run starts.
- **Pre-commands**: run bash commands before the agent starts executing.
- **Artifact uploads**: move generated files out of the sandbox with a presigned URL handshake.
- **Streaming and cancellation**: receive progress updates and stop runs cleanly.
Expand Down
3 changes: 2 additions & 1 deletion docs/content/docs/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"index",
"quickstart",
"python-client",
"typescript-client",
"agent-runtime"
]
}
}
109 changes: 75 additions & 34 deletions docs/content/docs/quickstart.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Quickstart
description: Start the runtime, connect from Python, and run your first prompt.
description: Start the runtime, connect from Python or TypeScript, and run your first prompt.
---

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
Expand Down Expand Up @@ -181,45 +181,86 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

## 2. Install the Client

```bash
pip install runtimeuse-client
```
<Tabs items={["Python", "TypeScript"]}>
<Tab>
```bash
pip install runtimeuse-client
```
</Tab>
<Tab>
```bash
npm install runtimeuse-client
```
</Tab>
</Tabs>

## 3. Connect and Query

Once you have a `ws_url`, the client flow is the same across providers:

```python
import asyncio

from runtimeuse_client import (
QueryOptions,
RuntimeEnvironmentDownloadableInterface,
RuntimeUseClient,
TextResult,
)


async def main(ws_url: str) -> None:
client = RuntimeUseClient(ws_url=ws_url)

result = await client.query(
prompt="Summarize the contents of this repository and list your favorite file.",
options=QueryOptions(
system_prompt="You are a helpful assistant.",
model="claude-sonnet-4-20250514", # gpt-5.4 for openai
pre_agent_downloadables=[
RuntimeEnvironmentDownloadableInterface(
download_url="https://github.com/openai/codex/archive/refs/heads/main.zip",
working_dir="/runtimeuse",
)
],
),
<Tabs items={["Python", "TypeScript"]}>
<Tab>
```python
import asyncio

from runtimeuse_client import (
QueryOptions,
RuntimeEnvironmentDownloadableInterface,
RuntimeUseClient,
TextResult,
)

assert isinstance(result.data, TextResult)
print(result.data.text)

async def main(ws_url: str) -> None:
client = RuntimeUseClient(ws_url=ws_url)

result = await client.query(
prompt="Summarize the contents of this repository and list your favorite file.",
options=QueryOptions(
system_prompt="You are a helpful assistant.",
model="claude-sonnet-4-20250514", # gpt-5.4 for openai
pre_agent_downloadables=[
RuntimeEnvironmentDownloadableInterface(
download_url="https://github.com/openai/codex/archive/refs/heads/main.zip",
working_dir="/runtimeuse",
)
],
),
)

assert isinstance(result.data, TextResult)
print(result.data.text)


asyncio.run(main(ws_url))
```
asyncio.run(main(ws_url))
```
</Tab>
<Tab>
```typescript
import {
RuntimeUseClient,
type TextResult,
} from "runtimeuse-client";

const client = new RuntimeUseClient({ wsUrl: ws_url });

const result = await client.query(
"Summarize the contents of this repository and list your favorite file.",
{
system_prompt: "You are a helpful assistant.",
model: "claude-sonnet-4-20250514", // gpt-5.4 for openai
pre_agent_downloadables: [
{
download_url:
"https://github.com/openai/codex/archive/refs/heads/main.zip",
working_dir: "/runtimeuse",
},
],
}
);

const data = result.data as TextResult;
console.log(data.text);
```
</Tab>
</Tabs>
201 changes: 201 additions & 0 deletions docs/content/docs/typescript-client.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
title: TypeScript Client
description: Connect to agent runtime in sandbox from TypeScript.
---

The [TypeScript client](https://www.npmjs.com/package/runtimeuse-client) is the control plane for RuntimeUse. It connects to the sandbox runtime, sends the invocation, and turns runtime messages into a single `QueryResult`.

```bash
npm install runtimeuse-client
```

## Basic Query

```typescript
import {
RuntimeUseClient,
type QueryOptions,
type TextResult,
} from "runtimeuse-client";

const client = new RuntimeUseClient({ wsUrl: "ws://localhost:8080" });

const result = await client.query("What is 2 + 2", {
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
});

const data = result.data as TextResult;
console.log(data.text);
console.log(result.metadata);
```

`query()` returns a `QueryResult` with:

- `data`: either `TextResult` (`.text`) or `StructuredOutputResult` (`.structured_output`)
- `metadata`: execution metadata returned by the runtime (includes token usage when available)

## Return Structured JSON

Pass `output_format_json_schema_str` when your application needs machine-readable output instead of free-form text. The result will be a `StructuredOutputResult`.

```typescript
import { z } from "zod";
import type { StructuredOutputResult } from "runtimeuse-client";

const RepoStats = z.object({
file_count: z.number(),
char_count: z.number(),
});

const result = await client.query(
"Inspect the repository and return the total file count and character count as JSON.",
{
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
output_format_json_schema_str: JSON.stringify({
type: "json_schema",
schema: z.toJSONSchema(RepoStats),
}),
}
);

const data = result.data as StructuredOutputResult;
const stats = RepoStats.parse(data.structured_output);
console.log(stats);
```

## Download Files into the Sandbox

Use `pre_agent_downloadables` to fetch a repository, zip archive, or any URL into the sandbox before the agent runs. This is the primary way to give the agent access to a codebase or dataset.

```typescript
import type { RuntimeEnvironmentDownloadable } from "runtimeuse-client";

const result = await client.query(
"Summarize the contents of this repository and list your favorite file.",
{
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
pre_agent_downloadables: [
{
download_url:
"https://github.com/openai/codex/archive/refs/heads/main.zip",
working_dir: "/runtimeuse",
},
],
}
);
```

The runtime downloads and extracts the file before handing control to the agent.

## Upload Artifacts

When the runtime requests an artifact upload, return a presigned URL and content type from `on_artifact_upload_request`. Set `artifacts_dir` to tell the runtime which sandbox directory contains the files to upload - both options must be provided together.

```typescript
import type {
ArtifactUploadRequestMessage,
ArtifactUploadResult,
} from "runtimeuse-client";

async function onArtifactUploadRequest(
request: ArtifactUploadRequestMessage
): Promise<ArtifactUploadResult> {
const presignedUrl = await createPresignedUrl(request.filename);
return {
presigned_url: presignedUrl,
content_type: "application/octet-stream",
};
}

const result = await client.query(
"Generate a report and save it as report.txt.",
{
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
artifacts_dir: "/runtimeuse/output",
on_artifact_upload_request: onArtifactUploadRequest,
}
);
```

## Stream Assistant Messages

Use `on_assistant_message` when you want intermediate progress while the run is still happening.

```typescript
import type { AssistantMessage } from "runtimeuse-client";

async function onAssistantMessage(msg: AssistantMessage): Promise<void> {
for (const block of msg.text_blocks) {
console.log(`[assistant] ${block}`);
}
}

const result = await client.query("Inspect this repository.", {
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
on_assistant_message: onAssistantMessage,
});
```

## Cancel a Run

Call `client.abort()` to cancel an in-flight query. The client sends a cancel message to the runtime and `query()` throws `CancelledException`.

```typescript
import { CancelledException } from "runtimeuse-client";

setTimeout(() => client.abort(), 5000);

try {
await client.query("Do the thing.", options);
} catch (err) {
if (err instanceof CancelledException) {
console.log("Run was cancelled");
}
}
```

## Set a Timeout

Use `timeout` (in seconds) to limit how long a query can run. If the limit is exceeded, `query()` throws a `TimeoutError`.

```typescript
const result = await client.query("Do the thing.", {
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
timeout: 120,
});
```

## Redact Secrets

Pass `secrets_to_redact` to strip sensitive strings from any output or logs that leave the sandbox.

```typescript
const result = await client.query("Check the API status.", {
system_prompt: "You are a helpful assistant.",
model: "gpt-5.3",
secrets_to_redact: ["sk-live-abc123", "my_db_password"],
});
```

## Handle Errors

`query()` throws `AgentRuntimeError` if the runtime sends back an error. The exception carries `.error` (the error message) and `.metadata`.

```typescript
import { AgentRuntimeError } from "runtimeuse-client";

try {
const result = await client.query("Do the thing.", options);
} catch (err) {
if (err instanceof AgentRuntimeError) {
console.log(`Runtime error: ${err.error}`);
console.log(`Metadata: ${JSON.stringify(err.metadata)}`);
}
}
```
3 changes: 3 additions & 0 deletions packages/runtimeuse-client-ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
.env
Loading