Skip to content
Planned · Not yet published

SDK

A thin Python async wrapper over the REST API. Planned — not yet published.

The Python SDK is on our roadmap but hasn't been published to PyPI yet. This page documents the planned API surface so you can preview the ergonomics. For now, use the REST API directly (see api-reference.html) — every endpoint is stable and documented.

pip install frontal-sdk # planned — not yet on PyPI

Package name reserved. Star the repo to get notified when we publish.

Planned Quick Start

example.py
import asyncio
from frontal import FrontalClient

async def main():
    client = FrontalClient(base_url="http://localhost:8400")
    
    # Create project
    project = await client.projects.create(
        name="my-backend",
        root_path="/code/my-backend",
        toolchain="python",
    )
    
    # Submit goal
    intake = await client.intake.submit(
        project_id=project.id,
        goal="Add Stripe checkout to the cart page",
        locale="en",
    )
    
    # Approve plan (after answering clarifying questions)
    plan = await client.plans.generate(intake.id)
    await client.plans.approve(plan.id)
    
    # Stream live events
    async for event in client.events.stream(project.id):
        print(f"[{event.type}] {event.summary}")

asyncio.run(main())

Planned API Surface

v0.1.0 — all async, all typed with Pydantic models.

FrontalClient

Main entrypoint. FrontalClient(base_url, token=None)

client.workspaces

.list(), .create(name), .get(id), .update(id, ...)

client.projects

.list(), .create(...), .get(id), .delete(id), .events(id)

client.intake

.submit(project_id, goal, locale), .answer(intake_id, answers)

client.plans

.generate(intake_id), .get(id), .approve(id), .reject(id)

client.sessions

.start(task_id), .prompt(id, text), .abort(id), .events(id) (async iterator)

client.tasks

.create(...), .get(id), .run(id), .rollback(id), .diff(id)

client.memory

.rebuild(project_id), .context_pack(project_id, task_id), .search(project_id, query)

client.events

.stream(project_id) — async iterator yielding SSE events

client.gateway

.chat(...), .transcribe(audio_bytes), .models()

Examples

Subscribe to live events

events.py
async for event in client.events.stream(project_id):
    if event.type == "tool_call":
        print(f"Tool: {event.tool_name}")
    elif event.type == "merge_completed":
        print(f"✓ Task merged: {event.task_id}")
        break

Rollback from point

rollback.py
# Find the snapshot to rollback to
snapshots = await client.sessions.snapshots(session_id)
target = snapshots[-5]  # 5 steps back

# Rollback
await client.sessions.rollback_from_point(
    session_id,
    snapshot_id=target.id,
    correction="Revert the database schema change",
)

Raw HTTP fallback (use this today)

httpx_example.py
import httpx

async with httpx.AsyncClient(base_url="http://localhost:8400") as client:
    # Create project
    r = await client.post("/api/projects", json={
        "name": "my-backend",
        "root_path": "/code/my-backend",
        "toolchain": "python",
    })
    project = r.json()
    
    # Stream events
    async with client.stream("GET", f"/api/projects/{project['id']}/events") as resp:
        async for line in resp.aiter_lines():
            if line.startswith("data: "):
                print(line[6:])

What's planned for v0.1.0

  • Async/await first (httpx under the hood)
  • Typed responses (Pydantic models)
  • SSE streaming as async iterators
  • Sync variant (for scripts)
  • TypeScript SDK (separate package)
  • CLI tool (frontal command)

Why we haven't shipped it yet

We're shipping the engine first. The SDK is a thin wrapper — every endpoint it calls is already stable and documented in api-reference.html. If you need Python ergonomics today, the httpx example above is ~10 lines of boilerplate. We'd rather ship the SDK once and get it right than rush a half-baked v0.0.1.

Want to use Frontal in Python today?

Start with the REST API.
It's already stable.