Building an AI-Powered Function Orchestrator: When AI Becomes Your Code Planner
2 October, 2025

As developers, we constantly face a dilemma: how do we make our code flexible enough to handle natural human requests without hardcoding every possible scenario?
While working on various automation projects, I kept running into the same pattern—users would ask for something in plain English, like "Can you calculate 2+25-4^2? or "Process these files and send me a summary", but my code was rigid, expecting specific formats and predefined workflows.
The breakthrough came when I realized: What if AI handled the planning, and I just focused on building solid, reusable functions? Instead of trying to anticipate every user request, let AI interpret the intent and dynamically orchestrate my functions.
This post walks through building a mini AI agent framework that separates what you can do (functions) from how to do it (AI planning). The result? Code that adapts to human intent rather than forcing humans to adapt to your interface.
The Problem: Traditional Code vs. Human Intent
How many times have you written code that looks like this?
def complex_math_solver(expression):
# Parse expression
# Apply PEMDAS rules
# Handle edge cases
# Return result
pass
The problem? You're cramming parsing logic, mathematical rules, and execution into one monolithic function. What if we could separate these concerns entirely?
The Solution: AI as a Function Orchestrator
Instead of hardcoding business logic, what if we let AI handle the planning while we focus on building atomic, reusable functions?
Here's the architecture:
Step 1: Define Atomic Functions
First, we create simple, single-purpose functions that do one thing well. Think of these as your building blocks—each function is pure, testable, and completely independent. The key is keeping them atomic so AI can combine them in any order to solve complex problems.
def sum(a, b):
return a + b
def multiply(a, b):
return a * b
def power(a, b):
return a ** b
# Function registry for dynamic execution
FUNCTIONS = {
"sum": sum,
"multiply": multiply,
"power": power,
}
Step 2: Document Your Functions (For AI)
Next, we create clear documentation for each function. This isn't just good practice — it's essential for AI to understand what each function does and how to use it. Think of this as your function's "instruction manual" that AI reads to make smart planning decisions.
DOCS = {
"sum": {
"description": "Add two numbers",
"args": {
"a": {
"type": "number",
"description": "a float or int number",
},
"b": {
"type": "number",
"description": "a float or int number",
},
},
},
"multiply": {
"description": "Multiply two numbers",
"args": {
"a": {
"type": "number",
"description": "a float or int number",
},
"b": {
"type": "number",
"description": "a float or int number",
},
},
},
"power": {
"description": "Raise a to the power of b",
"args": {
"a": {
"type": "number",
"description": "a float or int number",
},
"b": {
"type": "number",
"description": "a float or int number",
},
},
},
}
Step 3: Let AI Generate Execution Plans
Finally, we let AI do the heavy lifting — interpreting natural language requests and creating step-by-step execution plans. The AI uses your function documentation to understand what's possible, then figures out the optimal sequence to achieve the user's goal.
def get_action_plan(user_query):
prompt = f"""
You are an AI planner. Convert the user's request into a step-by-step plan.
Available functions:
{json.dumps(DOCS, indent=2)}
User's query: "{user_query}"
Return a JSON plan with ordered steps.
"""
response = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
return json.loads(response.choices[0].message.content)
Real Example: "Solve 2+2*5+4^2"
When a user sends this request to the system, it gets passed to OpenAI along with the function documentation. The AI analyzes the mathematical expression, applies PEMDAS rules, and returns a structured JSON plan that breaks down the calculation into atomic steps using the available functions.
Input: Natural language request
AI Output: Structured execution plan
{
"steps": [
{ "function": "power", "args": { "a": 4, "b": 2 } },
{ "function": "multiply", "args": { "a": 2, "b": 5 } },
{ "function": "sum", "args": { "a": 2, "b": "<result_of_step_2>" } },
{
"function": "sum",
"args": { "a": "<result_of_step_3>", "b": "<result_of_step_1>" }
}
]
}
Execution Output:
Step 1: power(4, 2) → 16
Step 2: multiply(2, 5) → 10
Step 3: sum(2, 10) → 12
Step 4: sum(12, 16) → 28
Final Result: 28
The Magic: Dynamic Plan Execution
This function takes the AI-generated plan and executes it step by step. The key insight is result chaining—each step can reference outputs from previous steps using placeholders like <result_of_step_1>
. The system automatically resolves these references, creating a dynamic pipeline where complex calculations emerge from simple function compositions.
def execute_plan(plan):
results = {}
for idx, step in enumerate(plan["steps"], start=1):
func_name = step["function"]
args = step["args"]
# Replace placeholders with previous results
for k, v in args.items():
if isinstance(v, str) and v.startswith("<result_of_step_"):
step_idx = int(v.split("_")[-1].replace(">", ""))
args[k] = results[step_idx]
# Execute function dynamically
func = FUNCTIONS[func_name]
result = func(**args)
results[idx] = result
print(f"Step {idx}: {func_name}({args}) → {result}")
return results[len(results)]
Why This Architecture Wins
Separation of Concerns
You write: Pure, testable functions
AI handles: Complex planning and orchestration
System manages: Execution flow and state
Human-in-the-Loop Safety
if "error" in plan:
print("❌ Error in plan generation:")
print(plan["error"]["message"])
sys.exit(1) # Safe exit on planning failures
For example, if a user asks "Divide 10 by 0 and add 5", the AI can detect this is mathematically impossible and return an error response like:
{
"error": {
"message": "Cannot divide by zero - this operation is undefined in mathematics"
}
}
This prevents dangerous operations from executing and provides clear feedback to users.
Infinite Extensibility
Today, it's math functions:
FUNCTIONS = {
"sum": sum,
"multiply": multiply,
"divide": divide
}
Tomorrow it could be anything:
FUNCTIONS = {
"read_file": read_file,
"send_email": send_email,
"query_database": query_db,
"fetch_weather": weather_api,
"analyze_sentiment": sentiment,
}
Real-World Applications
File Operations
"Take all .txt files in /docs, extract headings, and create a summary document"
Required Functions: list_files()
, read_file()
, extract_headings()
, create_document()
, write_file()
API Orchestration
"Get weather for New York, if it's raining, send a Slack message to #general"
Required Functions: fetch_weather()
, check_condition()
, send_slack_message()
Data Pipeline
"Load sales.csv, calculate monthly averages, generate a chart, and email it to the team"
Required Functions: load_csv()
, calculate_average()
, group_by_month()
, generate_chart()
, send_email()
MCP Server Integration
"Query our customer database, analyze sentiment of recent feedback, and create a dashboard"
Required Functions: query_database()
, analyze_sentiment()
, aggregate_data()
, create_dashboard()
, save_report()
The Bigger Picture
This isn't just a math solver — it's a mini AI agent framework. The system provides:
Function Library: Atomic, reusable components
AI Planner: Intelligent request interpretation
Execution Engine: Safe, traceable function orchestration
Human Oversight: Approval and error handling
What's Next?
Add more function types (file ops, API calls)
Implement approval workflows (show plan before execution)
Add function validation (type checking, parameter validation)
Build a web interface (make it accessible to non-developers)
Integrate with MCP servers (extend to complex business logic)
The bottom line: Stop hardcoding business logic. Let AI handle the planning, you handle the implementation. The result? More flexible, maintainable, and extensible code that adapts to user intent rather than forcing users to adapt to your interface.
I share tips on how to get started with freelancing, remote jobs, developer-related stuff, startup ecosystem, and lots of insider secrets with my subscribers.