Skip to main content
Version: v2.0

Python Sandbox

The Python sandbox lets you deploy any Python function as a callable tool. The function runs in an isolated environment and can be used standalone or attached to an agent.

Setup

pip install aixplain
from aixplain import Aixplain
import inspect
import time

aix = Aixplain(api_key="YOUR_API_KEY")

Quick start

def add_numbers(a: int, b: int):
return a + b

script_tool = aix.Tool(
name=f"Addition Tool {int(time.time())}",
integration="688779d8bfb8e46c273982ca", # Python Sandbox
config={
"code": inspect.getsource(add_numbers),
"function_name": "add_numbers",
},
)
script_tool.save()

result = script_tool.run(data={"a": 4, "b": 6}, action="add_numbers")
print(result.data) # 10
Show output

Create a script tool

1. Define and extract the function

Use inspect.getsource() to capture the function source as a string:

def calculate_statistics(numbers: list):
import statistics
return {
"mean": statistics.mean(numbers),
"median": statistics.median(numbers),
"stdev": statistics.stdev(numbers) if len(numbers) > 1 else 0,
"count": len(numbers),
}

script_content = inspect.getsource(calculate_statistics)

To load from a file instead:

with open("my_function.py") as f:
script_content = f.read()

Function requirements:

Most legacy authoring rules have been relaxed — multi-line def signatures, short parameter names, default values, missing type hints, top-level imports, and zero-argument functions all work. The only hard constraints today are:

  • function_name must exactly match a function defined in code. Helper functions in the same file are fine — only the one named by function_name is registered as the tool
  • Do not use bool parameters. The runtime serializer emits JSON true/false (lowercase), which then errors inside Python with NameError: name 'true' is not defined. Use int (0/1) instead until this is fixed
  • Avoid returning tuples or unpacking multiple values. Tuple returns round-trip as a string repr (e.g. "(2, 3)") rather than structured data. Return a dict or list when you need more than one value
  • Return values must be JSON-serialisable (dicts, lists, strings, numbers)

Type hints are no longer enforced, but we still recommend them — they help the agent infer a clean tool schema and make the function easier to call correctly.

2. Save the tool

stats_tool = aix.Tool(
name=f"Statistics Calculator {int(time.time())}",
integration="688779d8bfb8e46c273982ca",
config={
"code": script_content,
"function_name": "calculate_statistics",
},
)
stats_tool.save()
Config keyRequiredDescription
codeComplete function source as a string
function_nameName of the function to expose — must match the definition in code

3. Run the function

result = stats_tool.run(
data={"numbers": [10, 20, 30, 40, 50]},
action="calculate_statistics",
)
print(result.data)
Show output

Pass parameters as a dict with keys matching the function's argument names. If the tool has only one action, the action parameter can be omitted.

Examples

Text processing

def process_text(text: str, uppercase: str):
result = text.strip()
if uppercase == "True":
result = result.upper()
return {"original": text, "processed": result, "length": len(result)}

text_tool = aix.Tool(
name=f"Text Processor {int(time.time())}",
integration="688779d8bfb8e46c273982ca",
config={"code": inspect.getsource(process_text), "function_name": "process_text"},
)
text_tool.save()

result = text_tool.run(
data={"text": " hello world ", "uppercase": "True"},
action="process_text",
)
print(result.data)
Show output

Record filtering

def transform_records(records: list, filter_key: str, filter_value: str):
filtered = [r for r in records if r.get(filter_key) == filter_value]
return {
"total_input": len(records),
"total_output": len(filtered),
"filtered_records": filtered,
}

transform_tool = aix.Tool(
name=f"Record Transformer {int(time.time())}",
integration="688779d8bfb8e46c273982ca",
config={"code": inspect.getsource(transform_records), "function_name": "transform_records"},
)
transform_tool.save()

result = transform_tool.run(
data={
"records": [
{"id": 1, "category": "fruit", "name": "apple"},
{"id": 2, "category": "vegetable", "name": "carrot"},
{"id": 3, "category": "fruit", "name": "banana"},
],
"filter_key": "category",
"filter_value": "fruit",
},
action="transform_records",
)
print(result.data)
Show output

Error handling inside functions

Return errors as data rather than raising exceptions — the agent can reason about them:

def safe_divide(a: float, b: float):
if b == 0:
return {"error": "Cannot divide by zero", "result": None}
return {"result": a / b, "error": None}

Use with agents

note
# replaces: LangChain @tool decorator + StructuredTool + manual schema definition
# Python function becomes an agent tool directly; schema inferred automatically
def calculate_discount(price: float, discount_percent: float):
discount = price * (discount_percent / 100)
return {
"original_price": price,
"discount_amount": round(discount, 2),
"final_price": round(price - discount, 2),
}

discount_tool = aix.Tool(
name=f"Discount Calculator {int(time.time())}",
integration="688779d8bfb8e46c273982ca",
config={"code": inspect.getsource(calculate_discount), "function_name": "calculate_discount"},
)
discount_tool.save()

agent = aix.Agent(
name="Pricing Assistant",
description="Calculates prices with discounts.",
instructions="Use the discount calculator tool to compute final prices. Always show the original price, discount amount, and final price.",
tools=[discount_tool],
)
agent.save()

response = agent.run("What's the final price for a $100 item with 20% off?")
print(response.data.output)
Show output

Troubleshooting

function_name not found Confirm the value in config["function_name"] matches the function name in config["code"] exactly. Print script_content to verify what was captured.

Import errors in the sandbox Only Python standard library modules and commonly available packages are supported. Top-level import statements now work — you no longer need to move every import inside the function body — but if a package is unavailable in the sandbox runtime you'll see an ImportError at call time.

Boolean parameters errors out with NameError: name 'true' is not defined The runtime serializer encodes bool arguments as JSON true/false (lowercase), which Python then rejects. Use an int (0/1) parameter and coerce inside the function as a workaround.

inspect.getsource() fails The function must be defined in a file, not typed interactively in a REPL. In notebooks, define the function and call inspect.getsource() in the same cell.

Type or serialisation errors Parameters and return values must be JSON-serialisable. Convert custom objects to dicts, lists, or primitives before returning.