Python SDK
Install the foilengine package and integrate NPC conversations into your Python project.
Installation
pip install foilengineQuick Start
from foilengine import FoilEngineClient
client = FoilEngineClient(api_key="pk_live_...")
# Discover your personas
personas = client.personas.list()
print(personas[0].name) # "Grumpy Barista"
# Initialize a session
session = client.chat.init_session(
persona_id=personas[0].id,
user_session_id="player-001",
player_name="Alex",
player_gender="non-binary",
)
print(session.message) # NPC's greeting
# Send a message
response = client.chat.send_message(
persona_id=personas[0].id,
message="What do you recommend?",
user_session_id="player-001",
)
print(response.message) # NPC's reply
print(response.current_state) # State machine state
print(response.score) # Session scoreConfiguration
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key | str | required | Your API key |
base_url | str | https://api.foilengine.io | API base URL (override for local dev) |
timeout | float | 30.0 | Request timeout in seconds |
max_retries | int | 3 | Max retries on 429/5xx errors |
Available Methods
Personas
| Method | Returns | Description |
|---|---|---|
client.personas.list() | list[Persona] | List all published personas |
Machines
| Method | Returns | Description |
|---|---|---|
client.machines.list(persona_id, user_session_id) | list[MachineInfo] | List available machines for a player |
Chat
| Method | Returns | Description |
|---|---|---|
client.chat.init_session(...) | SessionInit | Start a new conversation |
client.chat.send_message(...) | ChatResponse | Send a message, get NPC reply |
client.chat.get_session(...) | SessionStatus | Check if a session exists |
client.chat.get_history(...) | ChatHistory | Get full message history |
client.chat.reset(...) | ResetResult | Delete a session |
Async Support
Use AsyncFoilEngineClient for async/await:
from foilengine import AsyncFoilEngineClient
async def main():
async with AsyncFoilEngineClient(api_key="pk_live_...") as client:
personas = await client.personas.list_async()
response = await client.chat.send_message_async(
persona_id=personas[0].id,
message="Hello!",
user_session_id="player-001",
)
print(response.message)Error Handling
All API errors are raised as typed exceptions:
from foilengine import (
FoilEngineClient,
AuthenticationError,
NotFoundError,
RateLimitError,
)
client = FoilEngineClient(api_key="pk_live_...")
try:
session = client.chat.get_session("persona-id", "player-001")
except NotFoundError:
# No existing session — initialize one
session = client.chat.init_session(...)
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")| Exception | Status | When |
|---|---|---|
BadRequestError | 400 | Invalid UUID, missing fields |
AuthenticationError | 401 | Missing or invalid API key |
ForbiddenError | 403 | Not owner or persona unpublished |
NotFoundError | 404 | Resource not found |
RateLimitError | 429 | Rate limit exceeded |
ServerError | 500 | Internal server error |
💡Tip
The SDK automatically retries on 429 and 5xx errors with exponential backoff (up to 3 retries). You only need to handle errors that persist after retries.
Multi-Machine Example
# Discover available machines for a player
machines = client.machines.list(persona_id, "player-001")
for m in machines:
status = "active" if m.has_session else "available"
linked = " (linked)" if m.is_linked else ""
print(f" {m.name}: {status}{linked}")
# Start a specific machine
session = client.chat.init_session(
persona_id=persona_id,
user_session_id="player-001",
player_name="Alex",
player_gender="non-binary",
machine_id=machines[1].machine_id, # target a specific scenario
)