Skip to content
Merged
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
83 changes: 72 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ for event in client.chat.stream("Summarize sales by region"):
print(event["text"], end="", flush=True)

# Upload files with a question
response = client.chat.create(
"Analyze this data",
files=["./sales.csv"],
)
response = client.chat.create("Analyze this data", files=["./sales.csv"])
```

## Resources
Expand All @@ -43,43 +40,101 @@ response = client.chat.create(

```python
client.chat.list(limit=10)
client.chat.create("What connectors are available?")
client.chat.create("What connectors are available?", connector_ids=[1])
client.chat.create("Analyze this", files=["./data.csv"]) # multipart upload
client.chat.stream("Summarize revenue") # returns a Stream iterator
client.chat.get("chat-uuid")
client.chat.stream("Summarize revenue")
client.chat.cancel("chat-uuid")
```

### Connectors

`config` is the connector configuration as documented by `types()` — `connector_type`
plus a per-type block (e.g. `postgres`, `kdb`, `snowflake`).

```python
client.connectors.list()
client.connectors.types() # every connector type and its fields (self-describing)

cfg = {
"connector_type": "POSTGRES",
"name": "prod-db",
"postgres": {"host": "db.example.com", "port": 5432, "user": "ro", "password": "...", "database": "app"},
}
client.connectors.test(cfg) # {"success": bool, "error": str} — a failed connection is success=False, not an error
created = client.connectors.create(cfg, allow_sql_write_operations=False)
client.connectors.update(created["connector_id"], cfg)
client.connectors.delete(created["connector_id"])
```

### Models

```python
client.models.list() # models a key may pass as the chat `model` field
```

### Playbooks

```python
client.playbooks.list(limit=10)
pb = client.playbooks.create()
client.playbooks.get(pb["id"])
client.playbooks.update(pb["id"], name="Weekly Revenue", prompt="Summarize revenue by region")
client.playbooks.deploy(pb["id"])
client.playbooks.run(pb["id"])
client.playbooks.get(pb["id"])
client.playbooks.run(pb["id"]) # run(..., dry_run=True) to validate without sending
client.playbooks.delete(pb["id"])
```

### Sandbox

A sandbox is a stateful Python/SQL workspace. Start one, run code or load connector
data into DataFrames, manage its files, then stop it.

```python
sb = client.sandbox.start()
sb = client.sandbox.start() # start(sandbox_id="...") restarts a specific one
sid = sb["sandbox_id"]

client.sandbox.list(status="all") # also: limit=, cursor=
client.sandbox.status(sid)
client.sandbox.executions(sid) # recorded run history (limit=, cursor=)

# Run code / commands
client.sandbox.execute(sid, code="import pandas as pd; print(pd.__version__)")
client.sandbox.exec(sid, command="ls -la") # bash by default
client.sandbox.exec(sid, command="print('hi')", kind="python")

# Load connector data into a DataFrame (exactly one of query / tql_path)
client.sandbox.query(sid, connector_id=1, query="SELECT * FROM sales LIMIT 10", dataframe_name="sales")
client.sandbox.query(sid, connector_id=2, tql_path="portfolio/current_positions.tql", params={"as_of": "2026-01-01"}, max_rows=500)

# Files
client.sandbox.upload_file(sid, "./data.csv")
client.sandbox.status(sid)
client.sandbox.list_files(sid) # path="subdir" to scope
content: bytes = client.sandbox.download_file(sid, "out/report.csv")
client.sandbox.delete_file(sid, "out/report.csv")

# Library write-back
client.sandbox.library_diff(sid)
client.sandbox.create_library_patch(sid, title="Add metric", description="...", draft=True)

client.sandbox.stop(sid)
```

## Errors

Non-2xx responses raise typed exceptions, all subclasses of `textql.APIError`:

```python
from textql import TextQL, NotFoundError, RateLimitError, AuthenticationError

try:
client.chat.get("does-not-exist")
except NotFoundError as e:
print(e.status_code, e.request_id)
```

Also exported: `PermissionDeniedError`, `APITimeoutError`, `APIConnectionError`.

## Configuration

| Option | Env var | Default |
Expand All @@ -88,7 +143,13 @@ client.sandbox.stop(sid)
| `base_url` | `TEXTQL_BASE_URL` | `https://app.textql.com` |
| `timeout` | — | `60.0` seconds |

The `base_url` accepts a bare hostname (e.g. `app.textql.com`) or a full URL.
The `base_url` accepts a bare hostname (e.g. `app.textql.com`) or a full URL. The
client is a context manager:

```python
with TextQL(api_key="tql_...") as client:
client.connectors.list()
```

## Links

Expand Down
Loading