Python Example
Overview and Purpose and Demo
Why Use Python Functions in Your Custom Integrations?
Integrating Python functions into your Custom Integrations provides a flexible and powerful way to transform, enrich, and personalize the data returned by external endpoints before it’s presented to the user. Since Python has direct access to both the source data (from your chosen REST or GraphQL endpoint) and the LLM parameters (such as user inputs or contextual variables), it enables sophisticated manipulations that go far beyond simple data retrieval.
Block diagram
Below are eight examples illustrating the kinds of transformations and enhancements you can implement with Python functions:
-
Filtering & Extraction:
Scenario: You’ve fetched a large dataset of user activities from a GraphQL endpoint.
Action: Use Python to filter the dataset based on a specific user input parameter (e.g.,"task_type"
) and return only the entries that match that category.
Outcome: The LLM receives a concise, relevant subset of data that directly answers the user’s query. -
Data Aggregation & Summarization:
Scenario: A REST API returns raw sales numbers for multiple products.
Action: Python can sum total sales, compute averages, or calculate growth percentages before returning a single, informative result.
Outcome: Instead of merely listing raw figures, the LLM can provide a meaningful summary—e.g., “Total sales increased by 10% this quarter.” -
Unit Conversion & Formatting:
Scenario: The user requests temperature data from a weather API.
Action: Convert temperatures from Kelvin to Celsius or Fahrenheit using Python. Adjust number formatting, rounding decimals, or appending units.
Outcome: The LLM can present neatly formatted, user-friendly metrics tailored to the user’s preferred units. -
Data Merging & Contextualization:
Scenario: A user asks for detailed product specs. One endpoint returns product details, another returns shipping estimates, and the user input (llm["userLocation"]
) provides a location.
Action: Python merges and correlates these disparate data sources, filters shipping data based on the user’s location, and outputs a single integrated result.
Outcome: The LLM can describe both product features and estimated delivery times in one coherent answer. -
Calculating Derived Metrics:
Scenario: A fitness tracking API returns daily step counts for a user. The user asks, “How many steps did I average last week?”
Action: Python computes the weekly average from the returned daily totals and returns that number as the new source.
Outcome: The LLM gives a direct answer: “You averaged about 8,500 steps per day last week.” -
Data Cleansing & Validation:
Scenario: The endpoint returns user-generated content containing extraneous characters, poorly formatted text, or missing fields.
Action: Python cleans the data—removing unwanted characters, correcting formatting, handling missing values—and outputs a standardized dataset.
Outcome: The LLM can provide a professional, polished response, free from messy data artifacts. -
Enriching Responses With External Logic:
Scenario: The user provides a “userDailyTask” parameter asking how many hours they spent on “coding.” The API returns a table of tasks and hours.
Action: Python locates the “coding” entry, retrieves the hours, and inserts this information into a friendly sentence like “You spent 4 hours on coding today.”
Outcome: The LLM presents a refined, human-readable response that directly addresses the user’s query. -
Conditional Formatting & Tiered Responses:
Scenario: The user retrieves their bank transactions via a REST API and wants a summary.
Action: Python checks if certain thresholds are met—e.g., if spending exceeds a certain limit—and adds warnings or tips. For example, if spending is high, add a message suggesting budgeting advice.
Outcome: The LLM returns a dynamic, context-aware answer: “You spent $2,300 this month, which is above your usual budget. Consider reviewing your spending habits.”
Parameters
See the Edit Parameter dialog below:
In the Edit Parameter dialog it will define what will show up in this Edit Integration dialog.
For this example, we set the Handle Response -> LLM to process data (Defautl)
, and Source -> Rest API
, Enable Custom Function -> true
Edit Integration dialog
The endpoint returns this structured data
[
["Task", "Hours per Day"],
["Work", 11],
["Eat", 2],
["Commute", 2],
["Watch TV", 2],
["Sleep", 7]
]
-
Python receives two main objects:
llm
: Contains LLM parameters, includingllm["llm_query"]
, it is always passed to the Integration.source
: Contains the processed data from your chosen data source (if any), potentially post processed by JSONata, and potentially processed by Python.
The Python code
def how_many_hours(task,myData): # Loop through the list and find "task"
log_message(f"Task: {task}")
for row in myData:
if row[0] == task:
task_hours = row[1]
break
info = f"Hours of {task}: {task_hours}"
return info
result = how_many_hours(llm["userDailyTask"],source)
Output
Note this is restricted python, it allows you to do Safe things in python.
For debugging log_message
writes to the log, so you can review results
Always return you data to result
, this will replace the source data, that is sent to the LLM. If you need the source to go the LLM, then include it in result
Python has the object llm and souce available to it
You need to return the results to the variable results, this will update the souce with this data.
Here’s complete documentation for your Geo Location Store Finder integration, using your screenshots and content as reference. This is designed for your ai12z Copilot, site admin, or developer docs, with code, example flows, JSON, and system prompt for LLM config.
Atlas Geo Location Store Finder – ai12z Integration
Find nearby Atlas stores using your browser’s geo location, or any address/city a user enters. Results display as beautiful cards with Google Maps integration.
1. User Experience Overview
Example Chat Flow
- User: “Find a store”
- Copilot: “Could you please provide your current location or the city you’re in? This will help me find the nearest Atlas store for you.”
- Button: Use my current location
- User clicks button (or types an address)
- Copilot: “Ok”
- System receives coordinates and shows store cards sorted by distance.
- Clicking Google Map on a card gives a route and driving directions with estimated time and distance.
2. Integration Setup Screens
Properties Dialog
Define your integration in ai12z Portal:
- Name: Geo Location
- Description: Call this agent function whenever the user wants to find the location of a store or business, or uses phrases like: “Where is the nearest sports store?”
- Data Source: Rest API
- Handle Response: Carousel
- Custom Function: Enabled
3. LLM Parameters
location
: String. Can be a full address (e.g.,"123 Main St, Boston, MA"
) or latitude,longitude (e.g.,"42.3601,-71.0589"
).
4. Python Code for Store Sorting
def find_nearest_stores(address, source, max_distance_km=10000):
try:
stores = source["items"]
geolocator = Nominatim(user_agent="ai12z")
try:
location = geolocator.geocode(address, timeout=10)
except Exception as geo_err:
raise Exception(f"Network error during geocode: {geo_err}")
if not location:
raise Exception(f"Could not geocode address: {address}")
user_coords = (location.latitude, location.longitude)
log_message(f"User address geocoded to: {user_coords}")
result = []
for store in stores:
store_coords = (store['latitude'], store['longitude'])
distance_km = geodesic(user_coords, store_coords).kilometers
if distance_km <= max_distance_km:
store_with_distance = dict(store)
store_with_distance['distance_km'] = round(distance_km, 2)
result.append(store_with_distance)
result.sort(key=lambda x: x['distance_km'])
items = result
source["items"] = items
return {"success": True, "source": source}
except Exception as e:
log_message(f"ERROR in find_nearest_stores: {str(e)}")
return {"success": False, "error": str(e)}
# Main entry point: expects llm["location"] and source["items"]
address = llm.get("location", "Boston, MA")
result = find_nearest_stores(address, source)
5. Handlebars Card Template
<div class="atlas-store-list grid grid-cols-1 gap-6">
{{#each items}}
<div
class="atlas-store-card bg-white rounded-2xl shadow-lg border border-gray-200 flex flex-col md:flex-row overflow-hidden mb-4 transition hover:shadow-2xl hover:-translate-y-1 duration-200"
data-lat="{{latitude}}"
data-lng="{{longitude}}"
>
<div class="w-full md:w-1/3 flex-shrink-0 bg-gray-100">
<img
src="{{image}}"
alt="{{title}}"
class="atlas-store-img w-full h-40 object-cover md:h-full"
loading="lazy"
/>
</div>
<div class="flex-1 p-4 flex flex-col justify-between">
<div>
<h2 class="text-2xl font-bold text-sky-800 mb-1 flex items-center">
{{title}}
<span
class="inline-block ml-2 rounded-full bg-gradient-to-br from-sky-300 to-blue-200 px-3 py-1 text-xs font-semibold text-sky-900 shadow"
>Open</span
>
</h2>
<p class="text-gray-700 text-sm mb-2 font-medium">
{{short_description}}
</p>
<div class="flex flex-col gap-1 mb-3">
<span class="font-semibold text-gray-600 flex items-center">
<svg
class="inline mr-2 w-4 h-4 text-sky-700"
fill="none"
stroke="currentColor"
stroke-width="2"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.657 16.657L13.414 12.414a2 2 0 010-2.828l4.243-4.243m-5.657 5.657a4 4 0 110-5.657 4 4 0 010 5.657z"
/>
</svg>
{{address}}
</span>
<span class="text-xs text-sky-700 flex items-center">
<svg
class="inline mr-1 w-4 h-4 text-sky-600"
fill="none"
stroke="currentColor"
stroke-width="2"
viewBox="0 0 24 24"
>
<circle cx="12" cy="12" r="10" />
<path d="M12 6v6l4 2" />
</svg>
{{hours}} - Distance {{distance_km}} km
</span>
</div>
<div class="flex flex-wrap gap-2 mb-2">
{{#each services}}
<span
class="atlas-badge bg-gradient-to-br from-blue-100 to-sky-100 text-sky-900 text-xs font-semibold px-3 py-1 rounded-xl border border-sky-200 shadow-sm"
>{{this}}</span
>
{{/each}}
</div>
</div>
<div
class="flex flex-row flex-wrap items-center mt-3 gap-2 overflow-visible"
>
<button
class="atlas-copy-btn text-sky-600 border border-sky-200 rounded px-3 py-2 text-xs hover:bg-sky-50 transition flex-shrink-0 min-w-[100px]"
onclick="ai12zBot.sendMessage('Google Map from your location to destination {{address}}','Google Map from your location to destination {{address}}')"
type="button"
>
Google Map
</button>
</div>
</div>
</div>
{{/each}}
</div>
6. JavaScript for Geo Location
ai12zBot.addEventListener("messageSent", (event) => {
const userMessage = String(event.detail).toLowerCase()
if (userMessage.includes("current location")) {
if (!navigator.geolocation) {
alert("Geolocation is not supported by your browser.")
return
}
navigator.geolocation.getCurrentPosition(
handleLocationSuccess,
handleLocationError
)
}
})
function handleLocationSuccess(position) {
const { latitude, longitude } = position.coords
setTimeout(() => {
ai12zBot.sendJSON(
{ lattitude: latitude, longitude: longitude },
"Using location data"
)
}, 5000)
}
function handleLocationError(err) {
const messages = {
1: "Location access was denied. Unable to retrieve your location.",
2: "Location information is unavailable. Please try again later.",
3: "Location request timed out. Please try again.",
}
alert(
messages[err.code] ||
"Unable to retrieve location. Please check your settings."
)
}
7. CSS Snippet
.atlas-store-list {
padding: 1rem 0;
}
.atlas-store-card {
box-shadow:
0 2px 10px 0 rgba(34, 71, 107, 0.05),
0 1.5px 6px 0 rgba(36, 63, 106, 0.07);
transition:
box-shadow 0.2s,
transform 0.2s;
}
.atlas-store-card:hover {
box-shadow:
0 8px 32px rgba(36, 71, 107, 0.2),
0 2.5px 12px rgba(36, 63, 106, 0.11);
transform: translateY(-3px) scale(1.01);
}
.atlas-store-img {
border-radius: 0 0 0 1rem;
}
.atlas-badge {
background: linear-gradient(90deg, #f0f6ff 0%, #d2ebff 100%);
}
.atlas-directions-btn,
.atlas-copy-btn {
cursor: pointer;
}
8. Sample Data File
{
"type": "dataFile",
"items": [
{
"title": "Atlas Boston",
"image": "https://cdn.ai12z.net/assets/web/atlas-boston.jpg",
"short_description": "Your go-to ski and snowboard shop in New England.",
"address": "280 Tremont St, Boston, MA 02116",
"services": ["Fitting", "Tuning", "Boot Customization"],
"hours": "Mon-Sat 10am-7pm, Sun 11am-5pm",
"latitude": 42.3496,
"longitude": -71.0645
}
// ...add more locations
]
}
9. System Prompt for LLM (ReAct)
Find a Store
If someone asks to help them find a store and they do not include the location:
- Example phrase: “I want to find a store”
- Example phrase: “Can you help me locate an Atlas store?”
- Example phrase: “Where can I buy Atlas sports equipment?”
- Example phrase: “Is there an Atlas store near me?”
- Example phrase: “How do I find an Atlas store?”
To assist them:
- Insert a button:
<button
type="button"
onclick="sendMessage('Request use my current location')"
class="ai12zBtn"
>
Use my current location
</button>(Do not insert the code block, just the button)
- If someone types in their location, use that address, don't prompt with the button, call the GeoLocation function.
- When the system receives "Request use my current location", respond by saying, Ok
- When you receive the next user message, the system will receive location attributes (latitude and longitude). Use this data to call the GeoLocation with the parameters you know for location.
10. Full Example User Flow
- User: “Find a store”
- Bot: “Could you please provide your current location or the city you’re in? This will help me find the nearest Atlas store for you.”
- Bot inserts button: [Use my current location]
- User clicks button
- Bot: “Ok”
- User's browser shares coordinates
- Bot: (finds nearest stores, displays as cards)
- User clicks Google Map on a card – Gets directions and distance.