In this guide, you’ll build a complete workflow that:
- Reads data from a Google Sheet
- Analyzes the data with AI
- Generates a summary report
Prerequisites
Make sure you’ve completed the Quickstart and have your API key configured.
Step 1: Create the Workflow
Start by creating a new Python file:
from fibonacci import Workflow, LLMNode, ToolNode
from dotenv import load_dotenv
import os
load_dotenv()
# Create the workflow
wf = Workflow(
name="Sales Report Generator",
description="Reads sales data and generates an analysis report",
tags=["sales", "reporting", "weekly"]
)
Step 2: Add the Data Source Node
Use a ToolNode to read data from Google Sheets:
# Node 1: Read sales data from Google Sheets
read_data = ToolNode(
id="read_sales",
name="Read Sales Data",
tool="google_sheets_read",
params={
"spreadsheet_id": "{{input.sheet_id}}",
"range": "{{input.range}}"
}
)
wf.add_node(read_data)
The {{input.sheet_id}} syntax is a template variable. It will be replaced with actual values when you run the workflow.
Step 3: Add the Analysis Node
Use an LLMNode to analyze the data:
# Node 2: Analyze the sales data
analyze = LLMNode(
id="analyze_data",
name="Analyze Sales Data",
instruction="""
Analyze this sales data and provide:
1. **Total Revenue**: Sum of all sales
2. **Top Performers**: Top 3 salespeople by revenue
3. **Trends**: Week-over-week comparison
4. **Concerns**: Any red flags or areas needing attention
Sales Data:
{{read_sales}}
Format your response with clear sections and bullet points.
""",
dependencies=["read_sales"], # This node depends on read_sales
model="claude-sonnet-4-5-20250929",
max_tokens=2000
)
wf.add_node(analyze)
Step 4: Add the Summary Node
Add another LLM node to create an executive summary:
# Node 3: Generate executive summary
summary = LLMNode(
id="executive_summary",
name="Executive Summary",
instruction="""
Based on this analysis, create a brief executive summary (3-4 sentences)
suitable for a busy executive. Focus on the most important insights and
any actions needed.
Analysis:
{{analyze_data}}
""",
dependencies=["analyze_data"]
)
wf.add_node(summary)
Step 5: Complete Workflow Code
Here’s the complete workflow:
from fibonacci import Workflow, LLMNode, ToolNode
from dotenv import load_dotenv
import os
load_dotenv()
# Create the workflow
wf = Workflow(
name="Sales Report Generator",
description="Reads sales data and generates an analysis report",
tags=["sales", "reporting", "weekly"]
)
# Node 1: Read data
read_data = ToolNode(
id="read_sales",
name="Read Sales Data",
tool="google_sheets_read",
params={
"spreadsheet_id": "{{input.sheet_id}}",
"range": "{{input.range}}"
}
)
# Node 2: Analyze
analyze = LLMNode(
id="analyze_data",
name="Analyze Sales Data",
instruction="""
Analyze this sales data and provide:
1. **Total Revenue**: Sum of all sales
2. **Top Performers**: Top 3 salespeople by revenue
3. **Trends**: Week-over-week comparison
4. **Concerns**: Any red flags or areas needing attention
Sales Data:
{{read_sales}}
""",
dependencies=["read_sales"]
)
# Node 3: Summary
summary = LLMNode(
id="executive_summary",
name="Executive Summary",
instruction="""
Create a brief executive summary (3-4 sentences) based on:
{{analyze_data}}
""",
dependencies=["analyze_data"]
)
# Add all nodes
wf.add_nodes([read_data, analyze, summary])
if __name__ == "__main__":
# Validate the workflow
wf.validate()
print("✅ Workflow validated!")
# Deploy
api_key = os.getenv("FIBONACCI_API_KEY")
workflow_id = wf.deploy(api_key=api_key)
print(f"✅ Deployed! ID: {workflow_id}")
# Execute
result = wf.run(input_data={
"sheet_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms", # Sample Sheet
"range": "Sales!A1:E10"
})
# Print results
print(f"\n📊 Status: {result.status}")
print(f"⏱️ Duration: {result.duration_seconds:.2f}s")
print(f"💰 Cost: ${result.total_cost:.4f}")
print("\n" + "="*60)
print("📈 ANALYSIS")
print("="*60)
print(result.output_data["analyze_data"])
print("\n" + "="*60)
print("📋 EXECUTIVE SUMMARY")
print("="*60)
print(result.output_data["executive_summary"])
Step 6: Run Your Workflow
Execute the workflow:
Expected output:
✅ Workflow validated!
✅ Deployed! ID: wf_abc123xyz
📊 Status: completed
⏱️ Duration: 4.32s
💰 Cost: $0.0023
============================================================
📈 ANALYSIS
============================================================
## Total Revenue
$1,234,567 for the period
## Top Performers
1. Sarah Johnson - $245,000
2. Mike Chen - $198,000
3. Lisa Park - $187,000
## Trends
- 12% increase from last week
- Strong performance in Enterprise segment
## Concerns
- SMB segment down 8%
- Two reps below quota
============================================================
📋 EXECUTIVE SUMMARY
============================================================
Sales exceeded targets by 12% this week, driven by strong Enterprise
performance from Sarah Johnson and Mike Chen. However, the SMB segment
declined 8%, requiring immediate attention. Recommend a team meeting
to address underperforming segments.
Understanding the Workflow
How Nodes Connect
- read_sales runs first (no dependencies)
- analyze_data waits for read_sales to complete
- executive_summary waits for analyze_data to complete
Template Variables
{{input.sheet_id}} - Replaced with input data at runtime
{{read_sales}} - Replaced with the output of the read_sales node
{{analyze_data}} - Replaced with the output of the analyze_data node
Adding Conditional Logic
Want to send an alert only if sales drop? Add a conditional node:
from fibonacci import ConditionalNode
# Check if we need an alert
check_alert = ConditionalNode(
id="check_alert",
name="Check if Alert Needed",
left_value="{{analyze_data}}",
operator="contains",
right_value="down",
true_branch=["send_alert"],
false_branch=[],
dependencies=["analyze_data"]
)
# Send Slack alert (only runs if condition is true)
send_alert = ToolNode(
id="send_alert",
name="Send Slack Alert",
tool="slack_send_message",
params={
"channel": "#sales-alerts",
"message": "⚠️ Sales Alert!\n\n{{executive_summary}}"
},
dependencies=["check_alert", "executive_summary"]
)
Exporting to YAML
You can also define workflows in YAML:
# Export your workflow to YAML
wf.to_yaml("sales_report.yaml")
This creates:
name: Sales Report Generator
description: Reads sales data and generates an analysis report
version: 1
is_active: true
tags:
- sales
- reporting
- weekly
nodes:
- id: read_sales
type: tool
name: Read Sales Data
tool_name: google_sheets_read
tool_params:
spreadsheet_id: "{{input.sheet_id}}"
range: "{{input.range}}"
- id: analyze_data
type: llm
name: Analyze Sales Data
instruction: |
Analyze this sales data and provide:
1. **Total Revenue**: Sum of all sales
2. **Top Performers**: Top 3 salespeople by revenue
...
dependencies:
- read_sales
- id: executive_summary
type: llm
name: Executive Summary
instruction: |
Create a brief executive summary...
dependencies:
- analyze_data
Next Steps
Great job! You’ve built a real workflow with multiple nodes, dependencies, and AI analysis.