Functions in Modus
Functions in Modus are stateless, request-response operations that handle
specific tasks with precision and speed. They get in, complete their objective,
and report back—no unnecessary complications, no lingering presence, just pure
operational efficiency.
You can think of a function as an endpoint—each function you write automatically
becomes a callable API endpoint that external systems can access.
Functions are the backbone of your app, handling everything from data gathering
to AI-powered analysis, all while maintaining clean, predictable behavior.
Core characteristics
Functions are stateless, request-response operations designed for fast,
predictable execution. They’re your go-to choice when you need quick data
processing, external API integration, or computational tasks without maintaining
state between requests.
Key capabilities
- Stateless: Each operation is independent with no memory of previous
requests
- Lightning fast: Optimized for sub-second response times
- Infinitely scalable: Deploy as many instances as needed
- Clean operations: Straightforward request-in, response-out pattern
- Auto-deployed: Exposed automatically as GraphQL queries or mutations
How functions become endpoints
When you deploy your functions, Modus automatically exposes them through a
GraphQL API. Your functions become either queries (for data retrieval) or
mutations (for data modifications) based on their operation type.
Data retrieval queries
Most functions become GraphQL queries—perfect for fetching and processing data:
// This function becomes a GraphQL query
func GatherThreatIntelligence(source string) (*ThreatReport, error) {
// Data gathering and processing operation
return fetchThreatData(source)
}
Your functions are now accessible via GraphQL:
query {
gatherThreatIntelligence(source: "network_logs") {
threatLevel
indicators
recommendations
}
}
Response:
{
"data": {
"gatherThreatIntelligence": {
"threatLevel": "HIGH",
"indicators": ["unusual_traffic", "failed_auth_attempts"],
"recommendations": ["immediate_investigation", "block_suspicious_ips"]
}
}
}
Data modification mutations
Functions that modify data automatically become GraphQL mutations. Modus detects
these by their operation prefixes:
// This becomes a GraphQL mutation
func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) {
// Create new security alert
return deploySecurityAlert(data)
}
Now you can execute data modifications:
mutation {
createSecurityAlert(
data: {
type: "INTRUSION_ATTEMPT"
severity: "CRITICAL"
source: "firewall_logs"
}
) {
alertId
status
timestamp
}
}
Response:
{
"data": {
"createSecurityAlert": {
"alertId": "alert_20250115_001",
"status": "ACTIVE",
"timestamp": "2025-01-15T14:30:00Z"
}
}
}
Functions starting with create
, update
, delete
, and similar action words
automatically become mutations.
Example: Weather intelligence analysis
Here’s a complete example that demonstrates how functions integrate external
APIs with AI models for intelligent data processing:
package main
import (
"fmt"
"strings"
"github.com/hypermodeinc/modus/sdk/go/pkg/http"
"github.com/hypermodeinc/modus/sdk/go/pkg/models"
"github.com/hypermodeinc/modus/sdk/go/pkg/models/openai"
)
type WeatherIntel struct {
City string `json:"city"`
Temperature float64 `json:"temperature"`
Conditions string `json:"conditions"`
Analysis string `json:"analysis"`
}
const modelName = "text-generator"
// Function: Gather weather data and provide tactical analysis
func GatherWeatherIntelligence(city string) (*WeatherIntel, error) {
// Fetch weather data from OpenWeatherMap API
url := fmt.Sprintf(
"https://api.openweathermap.org/data/2.5/weather?q=%s&appid={{API_KEY}}&units=metric",
city,
)
response, err := http.Fetch(url)
if err != nil {
return nil, err
}
if !response.Ok() {
return nil, fmt.Errorf(
"weather data retrieval failed: %d %s",
response.Status,
response.StatusText,
)
}
// Parse weather data
var weatherData struct {
Name string `json:"name"`
Main struct {
Temp float64 `json:"temp"`
} `json:"main"`
Weather []struct {
Description string `json:"description"`
} `json:"weather"`
}
response.JSON(&weatherData)
conditions := "unknown"
if len(weatherData.Weather) > 0 {
conditions = weatherData.Weather[0].Description
}
// Generate tactical analysis
analysis, err := analyzeTacticalConditions(
weatherData.Name,
weatherData.Main.Temp,
conditions,
)
if err != nil {
fmt.Printf("Analysis failed for %s: %v\n", weatherData.Name, err)
analysis = "Analysis unavailable - proceed with standard protocols"
}
return &WeatherIntel{
City: weatherData.Name,
Temperature: weatherData.Main.Temp,
Conditions: conditions,
Analysis: analysis,
}, nil
}
// Analyze weather conditions for tactical implications
func analyzeTacticalConditions(city string, temp float64, conditions string) (string, error) {
model, err := models.GetModel[openai.ChatModel](modelName)
if err != nil {
return "", err
}
prompt := `You are a tactical analyst evaluating weather conditions for field operations.
Provide a brief tactical assessment of how these weather conditions might impact
outdoor activities, visibility, and operational considerations in 1-2 sentences.`
content := fmt.Sprintf(
"Location: %s, Temperature: %.1f°C, Conditions: %s",
city,
temp,
conditions,
)
input, err := model.CreateInput(
openai.NewSystemMessage(prompt),
openai.NewUserMessage(content),
)
if err != nil {
return "", err
}
input.Temperature = 0.7
output, err := model.Invoke(input)
if err != nil {
return "", err
}
return strings.TrimSpace(output.Choices[0].Message.Content), nil
}
This function automatically becomes available as a GraphQL query:
query {
gatherWeatherIntelligence(city: "London") {
city
temperature
conditions
analysis
}
}
You’ll receive an intelligence report like:
{
"data": {
"gatherWeatherIntelligence": {
"city": "London",
"temperature": 12.3,
"conditions": "light rain",
"analysis": "
Light rain conditions will reduce visibility for surveillance operations and may impact equipment performance.
Recommend waterproof gear and consider delayed outdoor activities requiring clear sight lines."
}
}
}
Setting up the function
To use this function, you’ll need to:
Sign up for a free API key at OpenWeatherMap
Add the connections and models to your modus.json
:
{
"models": {
"text-generator": {
"sourceModel": "meta-llama/Llama-3.2-3B-Instruct",
"provider": "hugging-face",
"connection": "hypermode"
}
},
"connections": {
"weather-api": {
"type": "http",
"baseUrl": "https://api.openweathermap.org/",
"queryParameters": {
"appid": "{{API_KEY}}"
}
}
}
}
Set your API key in .env.dev.local
:
MODUS_WEATHER_API_API_KEY=your_openweathermap_api_key_here
When to use agents instead
Functions are perfect for most computational tasks, but when you need persistent
state, complex multi-step workflows, or processes that remember details across
multiple interactions, it’s time to consider agents.
Consider upgrading to agents when your use case requires:
- Persistent memory across multiple requests
- Conversation context that builds over time
- Multi-step workflows spanning extended periods
- Recovery from failures with state preservation
- Continuous monitoring with context retention
Your functions form the API backbone of your app—fast, reliable, and always
ready for the next request. They handle the immediate computational needs while
your agents manage the long-term stateful processes.