Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ For more details, see the [flmadm README](flmadm/README.md).
## Documentation

* [API Reference](docs/api/index.md)
* [SDKs](docs/sdk/index.md): [Rust SDK](docs/sdk/rust.md), [Python SDK](docs/sdk/python.md)
* [Rust API Tutorial](docs/tutorials/rust-api.md)
* [Local Development](docs/tutorials/local-development.md)
* [Runner Setup Guide](docs/tutorials/runner-setup.md)
* [Design Documents](docs/designs/)
Expand Down
5 changes: 4 additions & 1 deletion docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Flame exposes three gRPC services:
- [Frontend Service](frontend.md) - For client SDK developers
- [Backend Service](backend.md) - For executor/node developers
- [Instance Service](shim.md) - For application shim developers
- [SDK Guides](../sdk/index.md) - For application developers using Rust or Python

## Package

Expand Down Expand Up @@ -61,6 +62,8 @@ gRPC status codes are used for error reporting:
## Related Documentation

- [Flame README](../../README.md)
- [Rust SDK](../sdk/rust.md)
- [Python SDK](../sdk/python.md)
- [Local Development](../tutorials/local-development.md)
- [Runner Setup Guide](../tutorials/runner-setup.md)
- [Python SDK](../../sdk/python/README.md)
- [Python SDK README](../../sdk/python/README.md)
56 changes: 56 additions & 0 deletions docs/sdk/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Flame SDKs

Flame provides SDKs for building clients that submit work to Flame and services that run inside Flame executors.

| SDK | Use it for | Documentation |
|-----|------------|---------------|
| Rust SDK | Typed async clients, compiled services, high-throughput task submission, and object-cache workflows | [Rust SDK](rust.md) |
| Python SDK | Python services, scripts, agent and RL workflows, and dynamic packaging through Runner | [Python SDK](python.md) |

Both SDKs use the same Flame concepts:

- An application is the service registered in Flame.
- A session is a group of tasks for one application.
- A task is one unit of work inside a session.
- Common data is shared session input sent to every service instance.
- Object cache stores larger shared values, files, packages, and versioned objects.

## Configuration

Both SDKs read Flame configuration from `~/.flame/flame.yaml` and accept environment overrides from the Flame runtime:

```yaml
current-context: flame
contexts:
- name: flame
cluster:
endpoint: "http://127.0.0.1:8080"
cache:
endpoint: "grpc://127.0.0.1:9090"
```

Common environment overrides:

- `FLAME_ENDPOINT`
- `FLAME_CACHE_ENDPOINT`
- `FLAME_CA_FILE`

Use `https://` for the session-manager endpoint when TLS is enabled. Use `grpcs://` for the object-cache endpoint when cache TLS is enabled.

## Typical Workflow

1. Start a Flame cluster with Docker Compose or `flmadm`.
2. Deploy or register an application service.
3. Create a session for that application from a client.
4. Submit tasks with `invoke()` or `run()`.
5. Close the session when no more work will be submitted.

The SDKs wrap the gRPC APIs documented in [Flame API Reference](../api/index.md). Use the SDK pages for common application code and the API reference when implementing lower-level protocol integrations.

## Examples

- [Rust Pi example](../../examples/pi/rust/README.md)
- [Rust API tutorial](../tutorials/rust-api.md)
- [Rust Candle Based example](../../examples/candle/based/README.md)
- [Python Pi Runner example](../../examples/pi/python/README.md)
- [Python SDK API reference](../../sdk/python/docs/API.md)
220 changes: 220 additions & 0 deletions docs/sdk/python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# Flame Python SDK

The Python SDK is distributed as `flamepy`. It provides:

- A synchronous client for sessions, tasks, and application registration.
- A host-shim service base class for Python services.
- Object-cache helpers for pickled objects, files, and versioned references.
- The Runner API for packaging Python code and invoking functions or objects remotely.

## Install

Install the SDK package:

```bash
pip install flamepy
```

The package requires Python 3.9 or newer.

For local development from this repository:

```bash
python3 -m pip install -e sdk/python --user --no-build-isolation
```

## Configure A Client

The SDK reads `~/.flame/flame.yaml` by default:

```yaml
current-context: flame
contexts:
- name: flame
cluster:
endpoint: "http://127.0.0.1:8080"
cache:
endpoint: "grpc://127.0.0.1:9090"
package:
excludes:
- "*.log"
- "*.pkl"
```

Environment variables override the file:

- `FLAME_ENDPOINT`
- `FLAME_CACHE_ENDPOINT`
- `FLAME_CACHE_STORAGE`
- `FLAME_CA_FILE`

Use `https://` for the session-manager endpoint when TLS is enabled. Use `grpcs://` for the object-cache endpoint when cache TLS is enabled.

## Create Sessions And Run Tasks

The core client API uses bytes for task input, task output, and common data:

```python
from concurrent.futures import wait

import flamepy

session = flamepy.create_session(
"flmping",
min_instances=1,
resreq=flamepy.ResourceRequirement.from_string("cpu=1,mem=1g"),
)

output = session.invoke(b"hello")
print(output)

futures = [session.run(f"task {idx}".encode()) for idx in range(10)]
wait(futures)
outputs = [future.result() for future in futures]

session.close()
```

Use `session.create_task()`, `session.get_task()`, `session.list_tasks()`, and `session.watch_task()` when callers need explicit task objects or streamed task updates.

## Register Applications

Most users deploy applications with `flmctl deploy`. The SDK can also register an application directly:

```python
import flamepy

flamepy.register_application(
"echo",
{
"shim": flamepy.Shim.HOST,
"command": "python /opt/echo/service.py",
"description": "Echo service",
},
)
```

Use the same application name when creating a session:

```python
session = flamepy.create_session("echo")
```

## Write A Service

Subclass `FlameService` and run it with `flamepy.run()`:

```python
from typing import Optional

import flamepy


class Echo(flamepy.FlameService):
def on_session_enter(self, context: flamepy.SessionContext):
self.session_id = context.session_id
self.common_data = context.common_data()

def on_task_invoke(self, context: flamepy.TaskContext) -> Optional[bytes]:
return context.input

def on_session_leave(self):
self.session_id = None


if __name__ == "__main__":
flamepy.run(Echo())
```

The service runtime provides `FLAME_INSTANCE_ENDPOINT` and calls the service through a Unix domain socket. Service methods should return bytes or `None`.

## Use The Service Helper

For object-oriented or agent-style applications, `flamepy.service` provides a higher-level API that serializes Python objects through object cache:

```python
from flamepy import service

instance = service.FlameInstance()


@instance.entrypoint
def answer(question: str) -> str:
history = instance.context() or []
history.append(question)
instance.update_context(history)
return f"received {question}"


if __name__ == "__main__":
instance.run()
```

Clients use `flamepy.service.Session` with the deployed application name:

```python
from flamepy.service import Session

with Session("agent-app", ctx=[]) as session:
print(session.invoke("hello"))
print(session.context())
```

Use this helper when request, response, or session context objects are easier to model as Python objects than raw bytes. Use the core `FlameService` API when you need explicit byte-level protocol control.

## Use Object Cache

Top-level helpers store Python objects in Flame object cache:

```python
import flamepy

ref = flamepy.put_object("my-app/shared", {"temperature": 0.8})
value = flamepy.get_object(ref)

next_ref = flamepy.update_object(ref, {"temperature": 0.7})
next_value = flamepy.get_object(next_ref)
```

Object references are versioned. `version=0` forces a fresh download. Nonzero versions allow the client to reuse cached state and request newer patches when the cache server can provide them.

Lower-level helpers under `flamepy.core` and `flamepy.cache` also expose `ObjectKey`, `patch_object()`, `upload_object()`, `download_object()`, and `delete_objects()`.

## Use Runner

Runner packages the current Python project, registers a Flame application based on the configured runner template, and exposes Python callables or objects as remote services:

```python
from flamepy.runner import Runner


def square(value: int) -> int:
return value * value


with Runner("square-app") as runner:
svc = runner.service(square, warmup=2)
futures = [svc(idx) for idx in range(8)]
print(runner.get(futures))
```

Runner returns `ObjectFuture` values. Use `future.get()` to fetch a concrete result, `future.ref()` to get the `ObjectRef`, `runner.wait()` to wait for a batch, and `runner.select()` to iterate as results complete.

## API Map

| Area | Python API |
|------|------------|
| Connect | `flamepy.connect()` |
| Sessions | `create_session()`, `open_session()`, `get_session()`, `list_sessions()`, `close_session()` |
| Tasks | `Session.invoke()`, `Session.run()`, `Session.create_task()`, `Session.watch_task()` |
| Applications | `register_application()`, `unregister_application()`, `get_application()`, `list_applications()` |
| Services | `FlameService`, `flamepy.run()`, `flamepy.service.FlameInstance`, `flamepy.service.Session` |
| Objects | `put_object()`, `get_object()`, `update_object()`, `patch_object()`, `upload_object()`, `download_object()` |
| Runner | `Runner`, `Runner.service()`, `ObjectFuture` |

See also:

- [Python SDK API reference](../../sdk/python/docs/API.md)
- [Python SDK README](../../sdk/python/README.md)
- [Python Pi Runner example](../../examples/pi/python/README.md)
- [OpenAI agent service example](../../examples/agents/openai/README.md)
Loading
Loading