Python SDK
Execute Fruxon agents programmatically from Python — one-shot, streaming, multi-turn
The Fruxon Python SDK lets you execute agents from Python. For terminal usage, see the CLI guide.
Install
pip install fruxonRequires Python 3.10+.
Authentication
You need an API key and your organization identifier. Generate an API key from Settings → API Keys.
The constructor takes them explicitly:
from fruxon import FruxonClient
client = FruxonClient(
api_key="...",
org="acme-corp",
)Unlike the CLI, the SDK does not read FRUXON_API_KEY / FRUXON_ORG from the environment for you. If you want that behavior, read them yourself with os.environ.
Client options
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key | str | required | Organization API key |
org | str | required | Organization identifier |
base_url | str | "https://api.fruxon.com" | Override for self-hosted or staging environments |
timeout | float | 120.0 | Per-request timeout in seconds |
Execute an agent
result = client.execute(
"support-agent",
parameters={"question": "How do I reset my password?"},
)
print(result.response)
print(f"{result.trace.duration}ms · ${result.trace.total_cost:.4f}")
print(result.execution_record_id)execute() parameters
| Parameter | Type | Description |
|---|---|---|
agent | str | Agent ID (positional). |
parameters | dict | Inputs matching the agent's entry-point schema. |
session_id | str | Continue a multi-turn conversation (see below). |
attachments | list | File attachments to include with the request. |
chat_user | dict | Identify the end user (for traceability and access control). |
Result shape
execute() returns an ExecutionResult:
| Field | Type | Description |
|---|---|---|
response | str | The agent's text response. |
session_id | str | None | Pass back to continue this conversation. |
execution_record_id | str | Unique ID — use with fruxon trace or get_execution_record(). |
trace | ExecutionTrace | Cost, duration, token counts. |
links | list | Related links returned by the agent. |
The trace object:
| Field | Type | Description |
|---|---|---|
agent_id | str | Agent identifier. |
agent_revision | int | Revision number used. |
duration | int | Execution time in milliseconds. |
input_cost | float | Input token cost (USD). |
output_cost | float | Output token cost (USD). |
total_cost | float | Total cost (USD). |
Multi-turn conversations
Thread the returned session_id into the next call:
first = client.execute(
"support-agent",
parameters={"question": "What's your return policy?"},
)
follow_up = client.execute(
"support-agent",
parameters={"question": "What about international orders?"},
session_id=first.session_id,
)Streaming
For incremental text as the agent generates it:
for chunk in client.stream_text(
"support-agent",
parameters={"question": "Tell me about your service"},
):
print(chunk, end="", flush=True)For the full typed event stream — text chunks, tool calls, tool results, step traces, terminal events:
for event in client.stream("support-agent", parameters={"question": "Hi"}):
if event.event == "text":
print(event.data["chunk"], end="", flush=True)
elif event.event == "tool_call":
print(f"\n[tool call] {event.data}")
elif event.event == "tool_result":
print(f"\n[tool result] {event.data}")
elif event.event == "done":
trace = event.data.get("trace", {})
print(f"\n[done] {trace.get('duration')}ms")Event types: text, tool_call, tool_result, usage, status, step_trace, error, done.
Pin a specific revision
Useful for A/B testing or replaying historical traffic against a prior revision instead of the currently deployed one:
result = client.execute_revision(
"support-agent",
revision="42",
parameters={"question": "Hi"},
)Discovery
List every agent in your org, inspect one by ID, or fetch the input parameters a revision expects:
for agent in client.list_agents():
print(agent.id, agent.display_name, agent.current_revision)
one = client.get_agent("support-agent")
params = client.get_agent_parameters(
"support-agent",
revision=one.current_revision,
)Test a draft flow
Run a draft agent definition against an existing agent without publishing it — the programmatic side of fruxon agents test. request is the AgentTestRequest body: the candidate flow plus its subAgents, assets, integrationConfigs, llmConfigs, baseRevision, and runtime parameters.
request = {
"flow": {...}, # the candidate flow definition
"baseRevision": 3, # masked secrets resolve from this revision's configs
"parameters": {"query": "hello"},
}
# Sync — same ExecutionResult shape as execute()
result = client.test("support-agent", request)
print(result.response)
# Streaming — same StreamEvent shape as stream()
for event in client.stream_test("support-agent", request):
if event.event == "text":
print(event.data["chunk"], end="", flush=True)The SDK posts request verbatim — it deliberately doesn't model the broad, fast-evolving AgentTestRequest schema. Requires Editor access to the agent (the API key's owning user must be an editor or tenant admin).
Integrations & tools
The building blocks an agent draws on: an integration is a connection to an external service, and tools are the callable capabilities defined under it.
# Integrations
for integ in client.list_integrations(search="git", types=["CUSTOM"], tags=["ci"]):
print(integ.id, integ.type, integ.tags)
client.get_integration("github")
client.create_integration({"id": "github", "displayName": "GitHub", "configMetadata": {...}})
client.update_integration("github", {"displayName": "GitHub (renamed)"})
# A failed verification is a result, not an exception
check = client.verify_integration("github", {"authMetadataId": "...", "authConfig": {...}})
# Tools — always integration-scoped: (integration, tool) is the composite key
for tool in client.list_tools("github", types=["API"]):
print(tool.id, tool.tool_type, tool.action_type)
client.get_tool("github", "list_commits")
client.create_tool("github", {"id": "list_commits", "integrationId": "github", "descriptor": {...}})
client.update_tool("github", "list_commits", {...})
client.update_tool("github", "run_report", {...}, python=True) # Python-script tools
client.delete_tool("github", "list_commits")
# Test-run a tool before wiring it into an agent — returns the raw {response}
client.test_tool("github", {"descriptor": {...}, "parameters": {"repo": "fruxon-sdk"}})list_* / get_* return the narrow Integration / Tool dataclasses. The write methods post the request body verbatim — the structured configMetadata / descriptor payloads aren't modelled by the SDK — and return the same narrow view of the result. verify_integration and test_tool return the raw result dict.
Past executions
record = client.get_execution_record("support-agent", "rec-abc123")
print(record.status, record.total_cost)
# Full step-by-step trace as a raw dict
trace = client.get_execution_trace("support-agent", "rec-abc123")The record ID is printed at the end of every execute() and surfaced by fruxon run in the terminal.
Error handling
All API errors derive from FruxonError. Branch on the subclasses to give users actionable messages:
from fruxon import FruxonClient
from fruxon.exceptions import (
AuthenticationError,
ForbiddenError,
NotFoundError,
ValidationError,
FruxonConnectionError,
FruxonAPIError,
FruxonError,
)
client = FruxonClient(api_key="...", org="acme-corp")
try:
result = client.execute("my-agent", parameters={"input": "Hello"})
except AuthenticationError:
print("API key was rejected — generate a new one in Settings.")
except NotFoundError:
print("Agent not found in this organization.")
except ValidationError as e:
print(f"Bad request: {e}")
except FruxonConnectionError:
print("Could not reach the Fruxon API.")
except FruxonError as e:
print(f"Unexpected error: {e}")| Exception | When |
|---|---|
AuthenticationError | Invalid or missing API key (401). |
ForbiddenError | Insufficient permissions (403). |
NotFoundError | Agent or organization not found (404). |
ValidationError | Invalid parameters / missing required fields (400 / 422). |
FruxonConnectionError | Network error reaching the API. |
FruxonAPIError | Base class for HTTP-level errors (catch this for any API failure). |
FruxonError | Top-level base class for all SDK exceptions. |
Self-hosted / staging
Point at an alternate API host:
client = FruxonClient(
api_key="...",
org="acme-corp",
base_url="https://api.staging.fruxon.com",
)Links
- CLI guide — terminal usage of the same package (
fruxon run,fruxon chat, etc.). - PyPI package
- Execute API reference