@agentic_function Calling Sub-Functions in a Fixed Order#
Optionally calls the LLM, then invokes multiple sub-functions in the order hard-coded in the source.
Use Cases#
- Research flow: survey → find gap → generate ideas
- Paper flow: write draft → review → revise
- Data flow: collect → clean → analyze
- Any multi-step task with a fixed step order
Design Points#
- Use the
@agentic_functiondecorator - Call multiple sub-
@agentic_functions in a fixed order exec()is optional: don't call it (pure chaining), or call it multiple times (each call creates an exec child node)- Data is passed between sub-functions through Python variables
- A single function can call
exec()multiple times, and can call any number of other@agentic_functions
Example: No exec, Pure Chaining#
@agentic_function
def research_pipeline(task: str, runtime: Runtime) -> dict:
"""Run the full research flow: survey → find gap → generate ideas.
Args:
task: Research topic.
runtime: LLM runtime instance.
Returns:
A result dict containing survey, gaps, and ideas.
"""
survey = survey_topic(topic=task, runtime=runtime)
gaps = identify_gaps(survey=survey, runtime=runtime)
ideas = generate_ideas(gaps=gaps, runtime=runtime)
return {"survey": survey, "gaps": gaps, "ideas": ideas}
Example: Calling exec Once to Summarize#
@agentic_function
def research_pipeline(task: str, runtime: Runtime) -> str:
"""Run the full research flow and summarize the result.
Args:
task: Research topic.
runtime: LLM runtime instance.
Returns:
The consolidated research summary.
"""
survey = survey_topic(topic=task, runtime=runtime)
gaps = identify_gaps(survey=survey, runtime=runtime)
ideas = generate_ideas(gaps=gaps, runtime=runtime)
return runtime.exec(content=[
{"type": "text", "text": (
f"Survey:\n{survey}\n\n"
f"Gaps:\n{gaps}\n\n"
f"Ideas:\n{ideas}"
)},
])
Context Tree#
research_pipeline
├── survey_topic ← step 1
├── identify_gaps ← step 2
└── generate_ideas ← step 3
Passing Data Between Steps#
Data is passed between sub-functions through Python variables, with no LLM involvement:
survey = survey_topic(topic=task, runtime=runtime)
gaps = identify_gaps(survey=survey, runtime=runtime)
The return value of survey_topic is used directly as the input argument to identify_gaps.
Inserting Python Processing Between Steps#
survey = survey_topic(topic=task, runtime=runtime)
# Insert ordinary Python processing in between
key_points = extract_key_points(survey)
filtered = [p for p in key_points if p["relevance"] > 0.5]
gaps = identify_gaps(survey="\n".join(filtered), runtime=runtime)
Error Handling#
survey = survey_topic(topic=task, runtime=runtime)
if not survey or "error" in survey.lower():
return {"error": "Survey failed", "survey": survey}
gaps = identify_gaps(survey=survey, runtime=runtime)
Difference from "LLM-Chosen Calls"#
| Fixed-order calls | LLM-chosen calls | |
|---|---|---|
| Who decides the call order | Python code | The LLM |
| How many sub-functions are called | Multiple, all executed | One, chosen to execute |
| Whether a function registry is required | Not required | Required |
| Flexibility | Fixed flow | Varies with the task |
Last updated · 2026-08-13