FruxonDocs

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 fruxon

Requires 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

ParameterTypeDefaultDescription
api_keystrrequiredOrganization API key
orgstrrequiredOrganization identifier
base_urlstr"https://api.fruxon.com"Override for self-hosted or staging environments
timeoutfloat120.0Per-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

ParameterTypeDescription
agentstrAgent ID (positional).
parametersdictInputs matching the agent's entry-point schema.
session_idstrContinue a multi-turn conversation (see below).
attachmentslistFile attachments to include with the request.
chat_userdictIdentify the end user (for traceability and access control).

Result shape

execute() returns an ExecutionResult:

FieldTypeDescription
responsestrThe agent's text response.
session_idstr | NonePass back to continue this conversation.
execution_record_idstrUnique ID — use with fruxon trace or get_execution_record().
traceExecutionTraceCost, duration, token counts.
linkslistRelated links returned by the agent.

The trace object:

FieldTypeDescription
agent_idstrAgent identifier.
agent_revisionintRevision number used.
durationintExecution time in milliseconds.
input_costfloatInput token cost (USD).
output_costfloatOutput token cost (USD).
total_costfloatTotal 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}")
ExceptionWhen
AuthenticationErrorInvalid or missing API key (401).
ForbiddenErrorInsufficient permissions (403).
NotFoundErrorAgent or organization not found (404).
ValidationErrorInvalid parameters / missing required fields (400 / 422).
FruxonConnectionErrorNetwork error reaching the API.
FruxonAPIErrorBase class for HTTP-level errors (catch this for any API failure).
FruxonErrorTop-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",
)

On this page