From 687fc3ed5a5083cb3ffa54d3c2a6d8399588c7ec Mon Sep 17 00:00:00 2001 From: JairusSW Date: Mon, 30 Jun 2025 13:17:02 -0700 Subject: [PATCH 01/15] docs: add and update AssemblyScript examples --- modus/data-fetching.mdx | 6 +- modus/first-modus-agent.mdx | 220 +++++++++++++++++---------- modus/functions.mdx | 296 +++++++++++++++++++++++------------- modus/model-invoking.mdx | 17 +-- 4 files changed, 343 insertions(+), 196 deletions(-) diff --git a/modus/data-fetching.mdx b/modus/data-fetching.mdx index c715b6df..2d6c4ed2 100644 --- a/modus/data-fetching.mdx +++ b/modus/data-fetching.mdx @@ -157,9 +157,9 @@ export function getPerson(name: string): Person { const vars = new dgraph.Variables() vars.set("$name", name) - const resp = dgraph.execute( + const resp = dgraph.executeQuery( connection, - new dgraph.Request(new dgraph.Query(statement, vars)), + new dgraph.Query(statement, vars), ) const persons = JSON.parse(resp.Json).persons return persons[0] @@ -468,7 +468,7 @@ class Person { } @json class GetPersonResponse { - getPerson: Person | null + getPerson: Person | null = null } export function getPerson(name: string): Person | null { diff --git a/modus/first-modus-agent.mdx b/modus/first-modus-agent.mdx index 795f7615..f2f884db 100644 --- a/modus/first-modus-agent.mdx +++ b/modus/first-modus-agent.mdx @@ -103,104 +103,162 @@ AssemblyScript if you prefer. For AssemblyScript usage, refer to the Create a function that fetches data from an external API and uses AI for analysis: - - Create `intelligence.go`: - - ```go intelligence.go - package main - - import ( - "errors" - "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 IntelReport struct { - Quote string `json:"quote"` - Author string `json:"author"` - Analysis string `json:"analysis,omitempty"` - } + + + Create `intelligence.go`: + + ```go intelligence.go + package main - const modelName = "text-generator" + import ( + "errors" + "fmt" + "strings" - // Fetch a random quote and provide AI analysis - func GatherIntelligence() (*IntelReport, error) { - request := http.NewRequest("https://zenquotes.io/api/random") + "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" + ) - response, err := http.Fetch(request) - if err != nil { - return nil, err + type IntelReport struct { + Quote string `json:"quote"` + Author string `json:"author"` + Analysis string `json:"analysis,omitempty"` } - if !response.Ok() { - return nil, fmt.Errorf("request failed: %d %s", response.Status, response.StatusText) + + const modelName = "text-generator" + + // Fetch a random quote and provide AI analysis + func GatherIntelligence() (*IntelReport, error) { + request := http.NewRequest("https://zenquotes.io/api/random") + + response, err := http.Fetch(request) + if err != nil { + return nil, err + } + if !response.Ok() { + return nil, fmt.Errorf("request failed: %d %s", response.Status, response.StatusText) + } + + // Parse the API response + var quotes []IntelReport + response.JSON("es) + if len(quotes) == 0 { + return nil, errors.New("no data received") + } + + // Get the quote + intel := quotes[0] + + // Generate AI analysis + analysis, err := analyzeIntelligence(intel.Quote, intel.Author) + if err != nil { + fmt.Printf("AI analysis failed for %s: %v\n", intel.Author, err) + intel.Analysis = "Analysis unavailable" + } else { + intel.Analysis = analysis + } + + return &intel, nil } - // Parse the API response - var quotes []IntelReport - response.JSON("es) - if len(quotes) == 0 { - return nil, errors.New("no data received") + // Use AI to analyze the quote + func analyzeIntelligence(quote, author string) (string, error) { + model, err := models.GetModel[openai.ChatModel](modelName) + if err != nil { + return "", err + } + + prompt := `You are an analyst. + Provide a brief insight that captures the core meaning + and practical application of this wisdom in 1-2 sentences.` + content := fmt.Sprintf("Quote: \"%s\" - %s", quote, author) + + 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 } + ``` + + + Modify `index.ts` - // Get the quote - intel := quotes[0] + ```ts + import { http, models } from "@hypermode/modus-sdk-as"; + import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; - // Generate AI analysis - analysis, err := analyzeIntelligence(intel.Quote, intel.Author) - if err != nil { - fmt.Printf("AI analysis failed for %s: %v\n", intel.Author, err) - intel.Analysis = "Analysis unavailable" - } else { - intel.Analysis = analysis - } + export function sayHello(name: string | null = null): string { + return `Hello, ${name || "World"}!`; + } - return &intel, nil + @json + class IntelReport { + @alias("q") + quote!: string; + @alias("a") + author!: string; + analysis!: string; } - // Use AI to analyze the quote - func analyzeIntelligence(quote, author string) (string, error) { - model, err := models.GetModel[openai.ChatModel](modelName) - if err != nil { - return "", err - } + const modelName = "text-generator"; + + export function gatherIntelligence(): IntelReport { + const response = http.fetch("https://zenquotes.io/api/random"); + + if (response.status !== 200) + throw new Error("Request failed with status: " + response.status.toString() + " " + response.statusText); + + const quotes = response.json(); + + if (!quotes.length) + throw new Error("No data recieved"); + + const quote = quotes[0]; + const analysis = analyzeIntelligence(quote.quote, quote.author); + + quote.analysis = analysis; - prompt := `You are an analyst. + return quote; + } + + function analyzeIntelligence(quote: string, author: string): string { + const model = models.getModel(modelName); + + const prompt = `You are an analyst. Provide a brief insight that captures the core meaning - and practical application of this wisdom in 1-2 sentences.` - content := fmt.Sprintf("Quote: \"%s\" - %s", quote, author) + and practical application of this wisdom in 1-2 sentences.`; + const content = "Quote: " + quote + " - " + author; - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(content), - ) - if err != nil { - return "", err - } + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content) + ]); - input.Temperature = 0.7 + input.temperature = 0.7; - output, err := model.Invoke(input) - if err != nil { - return "", err - } + const output = model.invoke(input); - return strings.TrimSpace(output.Choices[0].Message.Content), nil + return output.choices[0].message.content.trim(); } ``` - + + - Restart your development server: - - ```sh - modus dev - ``` - Modus automatically generates a GraphQL API from your functions. Since your function is named `GatherIntelligence()`, it becomes a GraphQL query field called `gatherIntelligence`. @@ -208,13 +266,13 @@ AssemblyScript if you prefer. For AssemblyScript usage, refer to the The explorer is fully GraphQL-compatible, so you can issue this query: ```graphql - query { - gatherIntelligence { - quote - author - analysis + query { + gatherIntelligence { + quote + author + analysis + } } - } ``` You'll receive a response like: diff --git a/modus/functions.mdx b/modus/functions.mdx index 8ad1e3dd..365457ce 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -43,13 +43,22 @@ GraphQL API. Your functions become either **queries** (for data retrieval) or Most functions become GraphQL queries—perfect for fetching and processing data: -```go + +```go Go // This function becomes a GraphQL query func GatherThreatIntelligence(source string) (*ThreatReport, error) { - // Data gathering and processing operation - return fetchThreatData(source) + // Data gathering and processing operation + return fetchThreatData(source) } ``` +```ts AssemblyScript +// This function becomes a GraphQL query +export function gatherThreatIntelligence(source: string): ThreatReport { + // Data gathering and processing operation + return fetchThreatData(source) +} +``` + Your functions are now accessible via GraphQL: @@ -82,13 +91,22 @@ query { Functions that modify data automatically become GraphQL mutations. Modus detects these by their operation prefixes: -```go + +```go Go // This becomes a GraphQL mutation func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) { // Create new security alert return deploySecurityAlert(data) } ``` +```ts AssemblyScript +// This becomes a GraphQL mutation +export function createSecurityAlert(data: AlertInput): SecurityAlert { + // Create new security alert + return deploySecurityAlert(data) +} +``` + Now you can execute data modifications: @@ -130,119 +148,193 @@ automatically become mutations. Here's a complete example that demonstrates how functions integrate external APIs with AI models for intelligent data processing: -```go -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"` -} + + ```go Go + 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, - ) - } +// 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, ) - // 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, 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, + ) + } - response.JSON(&weatherData) + // 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"` + } - conditions := "unknown" - if len(weatherData.Weather) > 0 { - conditions = weatherData.Weather[0].Description - } + response.JSON(&weatherData) - // 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" - } + 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 - 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 - } +// 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 + } - 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 - input.Temperature = 0.7 + output, err := model.Invoke(input) + if err != nil { + return "", err + } - output, err := model.Invoke(input) - if err != nil { - return "", err - } + return strings.TrimSpace(output.Choices[0].Message.Content), nil - return strings.TrimSpace(output.Choices[0].Message.Content), nil } -``` + +```` +```ts AssemblyScript +import { http, models } from "@hypermode/modus-sdk-as"; +import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; + +@json +class WeatherIntel { + city!: string; + temperature!: f64; + conditions!: string; + analysis!: string; +} + +@json +class WeatherData { + name!: string; + main!: MainWeatherData; + weather!: WeatherDescription[]; +} + +@json +class MainWeatherData { + temp!: f64; +} + +@json +class WeatherDescription { + description!: string; +} + +const modelName = "text-generator"; + +export function gatherWeatherIntelligence(city: string): WeatherIntel { + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid={{API_KEY}}&units=metric`; + + const response = http.fetch(url); + + if (!response.ok) + throw new Error("Weather data retrieval failed: " + response.status.toString() + " " + response.statusText); + + const weatherData = response.json(); + + let conditions = "unknown" + + if (weatherData.weather.length) conditions = weatherData.weather[0].description; + + const analysis = analyzeTacticalConditions( + weatherData.name, + weatherData.main.temp, + conditions + ); + + return { + city: weatherData.name, + temperature: weatherData.main.temp, + conditions, + analysis + }; +} + +function analyzeTacticalConditions(city: string, temperature: f64, conditions: string): string { + const model = models.getModel(modelName); + + const 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.`; + + const content = `Location: ${city}, Temperatire: ${temperature}, Conditions: ${conditions}`; + + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content) + ]); + input.temperature = 0.7; + + const output = model.invoke(input); + + return output.choices[0].message.content.trim(); +} +```` + + This function automatically becomes available as a GraphQL query: diff --git a/modus/model-invoking.mdx b/modus/model-invoking.mdx index aafba0fe..0b67f0a1 100644 --- a/modus/model-invoking.mdx +++ b/modus/model-invoking.mdx @@ -159,7 +159,6 @@ func GenerateText(instruction, prompt string) (string, error) { import { models } from "@hypermode/modus-sdk-as" import { OpenAIChatModel, - ResponseFormat, SystemMessage, UserMessage, } from "@hypermode/modus-sdk-as/models/openai/chat" @@ -225,12 +224,8 @@ func ClassifyText(text string, threshold float32) (string, error) { ```ts AssemblyScript import { models } from "@hypermode/modus-sdk-as" -import { - ClassificationModel, - ClassifierResult, -} from "@hypermode/modus-sdk-as/models/experimental/classification" +import { ClassificationModel } from "@hypermode/modus-sdk-as/models/experimental/classification" -// this model name should match the one defined in the modus.json manifest file const modelName: string = "my-classifier" // this function takes input text and a probability threshold, and returns the @@ -241,12 +236,14 @@ export function classifyText(text: string, threshold: f32): string { const input = model.createInput([text]) const output = model.invoke(input) - const prediction = output.predictions[0] - if (prediction.confidence >= threshold) { - return prediction.label + const predictions = output.predictions + + const prediction = predictions[0] + if (prediction.confidence < threshold) { + return "" } - return "" + return prediction.label } ``` From 2dc30811b0c10ab9e7047574b891518ad3f3d10d Mon Sep 17 00:00:00 2001 From: JairusSW Date: Mon, 7 Jul 2025 17:48:29 -0700 Subject: [PATCH 02/15] fix: go weather example should not include query in url --- modus/functions.mdx | 186 +++++++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 89 deletions(-) diff --git a/modus/functions.mdx b/modus/functions.mdx index 365457ce..8473d517 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -150,110 +150,118 @@ APIs with AI models for intelligent data processing: ```go Go - 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"` } +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"` - } +// 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&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, + ) + } - response.JSON(&weatherData) + // 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"` + } - conditions := "unknown" - if len(weatherData.Weather) > 0 { - conditions = weatherData.Weather[0].Description - } + response.JSON(&weatherData) - // 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" - } + conditions := "unknown" + if len(weatherData.Weather) > 0 { + conditions = weatherData.Weather[0].Description + } - return &WeatherIntel{ - City: weatherData.Name, - Temperature: weatherData.Main.Temp, - Conditions: conditions, - Analysis: analysis, - }, nil + // 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 - } +// 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 + } - input.Temperature = 0.7 + 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 + } - output, err := model.Invoke(input) - if err != nil { - return "", err - } + input.Temperature = 0.7 - return strings.TrimSpace(output.Choices[0].Message.Content), nil + output, err := model.Invoke(input) + if err != nil { + return "", err + } + return strings.TrimSpace(output.Choices[0].Message.Content), nil } - -```` +``` ```ts AssemblyScript import { http, models } from "@hypermode/modus-sdk-as"; import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; From 98860bba763c6360149ecfba35063cd59c8a3936 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Mon, 7 Jul 2025 18:00:03 -0700 Subject: [PATCH 03/15] fix: go weather should escape query and not include query --- modus/functions.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modus/functions.mdx b/modus/functions.mdx index 8473d517..27a7f84d 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -154,6 +154,7 @@ package main import ( "fmt" + "net/url" "strings" "github.com/hypermodeinc/modus/sdk/go/pkg/http" "github.com/hypermodeinc/modus/sdk/go/pkg/models" @@ -171,10 +172,11 @@ const modelName = "text-generator" // Function: Gather weather data and provide tactical analysis func GatherWeatherIntelligence(city string) (*WeatherIntel, error) { + city = url.QueryEscape(city) // Fetch weather data from OpenWeatherMap API url := fmt.Sprintf( - "https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric", - city, + "https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric", + city, ) response, err := http.Fetch(url) From ebe1dfc2a9144726eec0aba94c57e8ac3c47f5e4 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Mon, 7 Jul 2025 18:04:22 -0700 Subject: [PATCH 04/15] fix: weather as should also encode uri component --- modus/functions.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modus/functions.mdx b/modus/functions.mdx index 27a7f84d..bd55ba2b 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -296,8 +296,8 @@ class WeatherDescription { const modelName = "text-generator"; export function gatherWeatherIntelligence(city: string): WeatherIntel { - const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid={{API_KEY}}&units=metric`; - + city = encodeURIComponent(city); + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric`; const response = http.fetch(url); if (!response.ok) @@ -342,7 +342,7 @@ function analyzeTacticalConditions(city: string, temperature: f64, conditions: s return output.choices[0].message.content.trim(); } -```` +``` From be307a880203cd599782a5f68de203b792953c66 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 12:20:09 -0700 Subject: [PATCH 05/15] fix: go knowledge graph example should actually work --- modus/knowledge-graphs.mdx | 506 +++++++++++++++++++------------------ 1 file changed, 264 insertions(+), 242 deletions(-) diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 6f6613a3..fbd59b31 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -84,67 +84,83 @@ When new Agent activity is detected in the Matrix, you need to process it quickly. This is perfect for a stateless function: ```go -type AgentSighting struct { - SightingID string `json:"sighting_id"` - AgentName string `json:"agent_name"` - Location string `json:"location"` - Behavior string `json:"behavior"` - ThreatLevel int `json:"threat_level"` - Timestamp string `json:"timestamp"` -} - -func ImportAgentSighting(sighting AgentSighting) (*string, error) { - // AI-powered analysis of the Agent behavior - analysis, err := analyzeAgentWithAI(sighting.Behavior) - if err != nil { - return nil, err - } +package main - // Store in knowledge graph - builds organizational knowledge - mutation := dgraph.NewMutation().WithSetJson(fmt.Sprintf(`{ - "dgraph.type": "AgentSighting", - "sighting_id": "%s", - "agent_name": "%s", - "location": "%s", - "behavior": "%s", - "threat_level": %d, - "timestamp": "%s", - "ai_analysis": "%s" - }`, sighting.SightingID, sighting.AgentName, sighting.Location, - sighting.Behavior, sighting.ThreatLevel, sighting.Timestamp, analysis)) - - err = dgraph.ExecuteMutations("dgraph", mutation) - if err != nil { - return nil, err - } +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/hypermodeinc/modus/sdk/go/pkg/agents" + "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" +) - result := fmt.Sprintf("Agent sighting processed: %s", sighting.SightingID) - return &result, nil +type AgentSighting struct { + SightingID string `json:"sighting_id"` + AgentName string `json:"agent_name"` + Location string `json:"location"` + Behavior string `json:"behavior"` + ThreatLevel int `json:"threat_level"` + Timestamp string `json:"timestamp"` + AiAnalysis *string `json:"ai_analysis,omitempty"` } -func analyzeAgentWithAI(behavior string) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } +type ThreatAnalysisResponse struct { + SightingCount int `json:"sighting_count"` + ActiveAgents []string `json:"active_agents"` + ThreatAssessment string `json:"threat_assessment"` + Recommendations []string `json:"recommendations"` +} - prompt := `Analyze this Agent behavior pattern and assess threat level, - behavioral changes, and tactical implications for resistance operations.` +type SightingsData struct { + Sightings []AgentSighting `json:"sightings"` +} - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(behavior), - ) - if err != nil { - return "", err - } - input.Temperature = 0.3 +func ImportAgentSighting(s AgentSighting) (*string, error) { + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis + + data, err := json.Marshal(s) + if err != nil { + return nil, err + } + + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } + + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil +} - output, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(output.Choices[0].Message.Content), nil +func analyzeAgentWithAI(behavior string) (string, error) { + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } + + prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage(behavior), + ) + if err != nil { + return "", err + } + input.Temperature = 0.3 + + out, err := model.Invoke(input) + if err != nil { + return "", err + } + return strings.TrimSpace(out.Choices[0].Message.Content), nil } ``` @@ -183,87 +199,102 @@ Now that we've got the Agent sighting data in our knowledge graph, let's analyze the broader threat landscape: ```go -type ThreatAnalysisResponse struct { - SightingCount int `json:"sighting_count"` - ActiveAgents []string `json:"active_agents"` - ThreatAssessment string `json:"threat_assessment"` - Recommendations []string `json:"recommendations"` +func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { + query := dgraph.NewQuery(` + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } + } + `).WithVariable("$since", since) + + resp, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } + + var data SightingsData + if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { + return nil, err + } + + assessment, err := generateThreatAssessment(data.Sightings) + if err != nil { + return nil, err + } + + return &ThreatAnalysisResponse{ + SightingCount: len(data.Sightings), + ActiveAgents: extractActiveAgents(data.Sightings), + ThreatAssessment: assessment, + Recommendations: generateRecommendations(len(data.Sightings)), + }, nil } -func AnalyzeAgentPatterns(timeRange string) (*ThreatAnalysisResponse, error) { - // Query organizational knowledge - traverses relationships - query := dgraph.NewQuery(` - query analyzeAgents($since: string) { - sightings(func: ge(timestamp, $since)) { - agent_name - behavior - threat_level - ai_analysis - } - } - `).WithVariable("$since", timeRange) - - response, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } - - // Parse and extract threat data - var data SightingsData - err = json.Unmarshal([]byte(response.Json), &data) - if err != nil { - return nil, err - } - - // Generate strategic assessment using AI with graph context - assessment, err := generateThreatAssessment(data.Sightings) - if err != nil { - return nil, err - } - - return &ThreatAnalysisResponse{ - SightingCount: len(data.Sightings), - ActiveAgents: extractActiveAgents(data.Sightings), - ThreatAssessment: assessment, - Recommendations: generateRecommendations(len(data.Sightings)), - }, nil +func generateThreatAssessment(sightings []AgentSighting) (string, error) { + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } + + prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + data, err := json.Marshal(sightings) + if err != nil { + return "", err + } + + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage("Agent surveillance data: "+string(data)), + ) + if err != nil { + return "", err + } + input.Temperature = 0.4 + + out, err := model.Invoke(input) + if err != nil { + return "", err + } + + return strings.TrimSpace(out.Choices[0].Message.Content), nil } -func generateThreatAssessment(sightings interface{}) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } - - prompt := `Based on these Agent sightings, provide a strategic threat - assessment focusing on behavioral patterns and risks to - resistance operations.` - - sightingsJson, err := json.Marshal(sightings) - if err != nil { - return "", err - } - - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(fmt.Sprintf("Agent surveillance data: %s", - string(sightingsJson))), - ) - if err != nil { - return "", err - } - input.Temperature = 0.4 - - output, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(output.Choices[0].Message.Content), nil +func extractActiveAgents(sightings []AgentSighting) []string { + seen := map[string]struct{}{} + var agents []string + for _, s := range sightings { + if _, ok := seen[s.AgentName]; !ok { + seen[s.AgentName] = struct{}{} + agents = append(agents, s.AgentName) + } + } + return agents } -// Helper functions for data extraction and recommendations -func extractActiveAgents(sightings []AgentSightingData) []string { /* ... */ } -func generateRecommendations(count int) []string { /* ... */ } +func generateRecommendations(count int) []string { + switch { + case count > 5: + return []string{ + "Implement additional security measures.", + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + case count > 2: + return []string{ + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + default: + return []string{"Implement additional security measures."} + } +} ``` Let's query our surveillance data: @@ -308,40 +339,37 @@ function to trigger them: ```go type SurveillanceAgent struct { - agents.AgentBase - MonitoredSectors []string `json:"monitored_sectors"` - SightingsTracked int `json:"sightings_tracked"` - RecentActivities []string `json:"recent_activities"` - LastSweepTime time.Time `json:"last_sweep_time"` + agents.AgentBase + MonitoredSectors []string `json:"monitored_sectors"` + SightingsTracked int `json:"sightings_tracked"` + RecentActivities []string `json:"recent_activities"` + LastSweepTime time.Time `json:"last_sweep_time"` } func (s *SurveillanceAgent) Name() string { - return "SurveillanceAgent" + return "SurveillanceAgent" } func (s *SurveillanceAgent) OnInitialize() error { - s.MonitoredSectors = []string{ - "Downtown Loop", "Megacity Financial", "Industrial District"} - s.SightingsTracked = 0 - s.RecentActivities = []string{} - s.LastSweepTime = time.Now() - return nil -} - -func (s *SurveillanceAgent) OnReceiveMessage( - msgName string, data string) (*string, error) { - switch msgName { - case "continuous_surveillance": - return s.processNewIntelligence() - case "get_status": - return s.getOperationalStatus() - } - return nil, fmt.Errorf("unrecognized directive: %s", msgName) + s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} + s.SightingsTracked = 0 + s.RecentActivities = []string{} + s.LastSweepTime = time.Now() + return nil +} + +func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { + switch msgName { + case "continuous_surveillance": + return s.processNewIntelligence() + case "get_status": + return s.getOperationalStatus() + } + return nil, fmt.Errorf("unrecognized directive: %s", msgName) } func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { - // Query knowledge graph for latest data since last sweep - query := dgraph.NewQuery(` + query := dgraph.NewQuery(` query getRecentSightings($since: string) { sightings(func: ge(timestamp, $since)) { agent_name @@ -351,64 +379,64 @@ func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { } `).WithVariable("$since", s.LastSweepTime.Format(time.RFC3339)) - _, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } - - // Update agent's surveillance state - s.LastSweepTime = time.Now() - s.SightingsTracked += 1 + _, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } - activity := fmt.Sprintf("Auto surveillance at %s", - s.LastSweepTime.Format("15:04:05")) - s.RecentActivities = append(s.RecentActivities, activity) + s.LastSweepTime = time.Now() + s.SightingsTracked++ + activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) + s.RecentActivities = append(s.RecentActivities, activity) - // Keep only last 3 activities - if len(s.RecentActivities) > 3 { - s.RecentActivities = s.RecentActivities[1:] - } + if len(s.RecentActivities) > 3 { + s.RecentActivities = s.RecentActivities[1:] + } - result := fmt.Sprintf(`Data processed automatically. - Tracking %d sightings. Matrix integrity: COMPROMISED`, - s.SightingsTracked) - return &result, nil + result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) + return &result, nil } func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { - status := fmt.Sprintf(`Surveillance Agent Status: + status := fmt.Sprintf(`Surveillance Agent Status: - Operational: Active - Monitoring %d sectors: %s - Last sweep: %s - Tracking %d ongoing sightings - Recent activities: %s`, - len(s.MonitoredSectors), - strings.Join(s.MonitoredSectors, ", "), - s.LastSweepTime.Format("2006-01-02 15:04:05"), - s.SightingsTracked, - strings.Join(s.RecentActivities, ", ")) - return &status, nil + len(s.MonitoredSectors), + strings.Join(s.MonitoredSectors, ", "), + s.LastSweepTime.Format("2006-01-02 15:04:05"), + s.SightingsTracked, + strings.Join(s.RecentActivities, ", "), + ) + return &status, nil } -func init() { agents.Register(&SurveillanceAgent{}) } +func (s *SurveillanceAgent) GetState() *string { return nil } +func (s *SurveillanceAgent) SetState(state *string) {} + +func init() { + agents.Register(&SurveillanceAgent{}) +} func DeploySurveillanceAgent() (string, error) { - agentInfo, err := agents.Start("SurveillanceAgent") - if err != nil { - return "", err - } - return agentInfo.Id, nil + agentInfo, err := agents.Start("SurveillanceAgent") + if err != nil { + return "", err + } + return agentInfo.Name + " - " + agentInfo.Id, nil } func GetSurveillanceStatus(agentId string) (string, error) { - result, err := agents.SendMessage(agentId, "get_status") - if err != nil { - return "", err - } - if result == nil { - return "", fmt.Errorf("no response from agent") - } - return *result, nil + result, err := agents.SendMessage(agentId, "get_status") + if err != nil { + return "", err + } + if result == nil { + return "", fmt.Errorf("no response from agent") + } + return *result, nil } ``` @@ -416,39 +444,31 @@ Now let's enhance our original import function to automatically trigger surveillance: ```go -func ImportAgentSighting(sighting AgentSighting) (*string, error) { - // AI-powered analysis of the Agent behavior - analysis, err := analyzeAgentWithAI(sighting.Behavior) - if err != nil { - return nil, err - } - - // Store in knowledge graph - builds organizational knowledge - mutation := dgraph.NewMutation().WithSetJson(fmt.Sprintf(`{ - "dgraph.type": "AgentSighting", - "sighting_id": "%s", - "agent_name": "%s", - "location": "%s", - "behavior": "%s", - "threat_level": %d, - "timestamp": "%s", - "ai_analysis": "%s" - }`, sighting.SightingID, sighting.AgentName, sighting.Location, - sighting.Behavior, sighting.ThreatLevel, sighting.Timestamp, analysis)) - - err = dgraph.ExecuteMutations("dgraph", mutation) - if err != nil { - return nil, err - } - - // Automatically trigger surveillance via async message - err = agents.SendMessageAsync("agent_neo_001", "continuous_surveillance") - if err != nil { - return nil, err - } - - result := fmt.Sprintf("Agent sighting processed: %s", sighting.SightingID) - return &result, nil +func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, error) { + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis + + data, err := json.Marshal(s) + if err != nil { + return nil, err + } + + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } + + if surveillanceAgentId != nil { + if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { + return nil, err + } + } + + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil } ``` @@ -507,7 +527,7 @@ messaging. Check the surveillance status: ```graphql query { - getSurveillanceStatus(agentId: "agent_neo_001") + surveillanceStatus(agentId: "agent_neo_001") } ``` @@ -516,14 +536,15 @@ query { ```json { "data": { - "getSurveillanceStatus": "Surveillance Agent Status: - - Operational: Active - - Monitoring 3 sectors: Downtown Loop, - Megacity Financial, Industrial District - - Last sweep: 2025-01-15 15:45:22 - - Tracking 2 ongoing sightings - - Recent activities: Auto surveillance at 14:30:05, - Auto surveillance at 15:45:22" + "surveillanceStatus": + "Surveillance Agent Status: + - Operational: Active + - Monitoring 3 sectors: Downtown Loop, + Megacity Financial, Industrial District + - Last sweep: 2025-01-15 15:45:22 + - Tracking 2 ongoing sightings + - Recent activities: Auto surveillance at 14:30:05, + Auto surveillance at 15:45:22" } } ``` @@ -552,12 +573,13 @@ query { "analyzeAgentPatterns": { "sightingCount": 2, "activeAgents": ["Smith", "Brown"], - "threatAssessment": "Critical escalation detected. Agent Smith's - enhanced replication capabilities combined with - Agent Brown's encryption countermeasures indicates - coordinated Matrix defense upgrade. Systematic - pattern suggests machines adapting to resistance - operations.", + "threatAssessment": + "Critical escalation detected. Agent Smith's + enhanced replication capabilities combined with + Agent Brown's encryption countermeasures indicates + coordinated Matrix defense upgrade. Systematic + pattern suggests machines adapting to resistance + operations.", "recommendations": [ "Emergency extraction protocols", "Activate deep cover cells", From 3c209a5d2d33d06b25d89438ea1ae35616b57825 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 12:26:19 -0700 Subject: [PATCH 06/15] fix: knowlege graph example should work out of the box --- modus/knowledge-graphs.mdx | 441 +++++++++++++++++++------------------ 1 file changed, 222 insertions(+), 219 deletions(-) diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index fbd59b31..347571d9 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -87,80 +87,78 @@ quickly. This is perfect for a stateless function: package main import ( - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/hypermodeinc/modus/sdk/go/pkg/agents" - "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" - "github.com/hypermodeinc/modus/sdk/go/pkg/models" - "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" + "encoding/json" + "fmt" + "strings" + + "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" ) type AgentSighting struct { - SightingID string `json:"sighting_id"` - AgentName string `json:"agent_name"` - Location string `json:"location"` - Behavior string `json:"behavior"` - ThreatLevel int `json:"threat_level"` - Timestamp string `json:"timestamp"` - AiAnalysis *string `json:"ai_analysis,omitempty"` + SightingID string `json:"sighting_id"` + AgentName string `json:"agent_name"` + Location string `json:"location"` + Behavior string `json:"behavior"` + ThreatLevel int `json:"threat_level"` + Timestamp string `json:"timestamp"` + AiAnalysis *string `json:"ai_analysis,omitempty"` } type ThreatAnalysisResponse struct { - SightingCount int `json:"sighting_count"` - ActiveAgents []string `json:"active_agents"` - ThreatAssessment string `json:"threat_assessment"` - Recommendations []string `json:"recommendations"` + SightingCount int `json:"sighting_count"` + ActiveAgents []string `json:"active_agents"` + ThreatAssessment string `json:"threat_assessment"` + Recommendations []string `json:"recommendations"` } type SightingsData struct { - Sightings []AgentSighting `json:"sightings"` + Sightings []AgentSighting `json:"sightings"` } func ImportAgentSighting(s AgentSighting) (*string, error) { - analysis, err := analyzeAgentWithAI(s.Behavior) - if err != nil { - return nil, err - } - s.AiAnalysis = &analysis + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis - data, err := json.Marshal(s) - if err != nil { - return nil, err - } + data, err := json.Marshal(s) + if err != nil { + return nil, err + } - mutation := dgraph.NewMutation().WithSetJson(string(data)) - if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { - return nil, err - } + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } - res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) - return &res, nil + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil } func analyzeAgentWithAI(behavior string) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } - - prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(behavior), - ) - if err != nil { - return "", err - } - input.Temperature = 0.3 - - out, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(out.Choices[0].Message.Content), nil + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } + + prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage(behavior), + ) + if err != nil { + return "", err + } + input.Temperature = 0.3 + + out, err := model.Invoke(input) + if err != nil { + return "", err + } + return strings.TrimSpace(out.Choices[0].Message.Content), nil } ``` @@ -200,100 +198,100 @@ the broader threat landscape: ```go func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { - query := dgraph.NewQuery(` - query analyzeAgents($since: string) { - sightings(func: ge(timestamp, $since)) { - sighting_id - agent_name - location - behavior - threat_level - timestamp - ai_analysis - } - } - `).WithVariable("$since", since) - - resp, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } - - var data SightingsData - if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { - return nil, err - } - - assessment, err := generateThreatAssessment(data.Sightings) - if err != nil { - return nil, err - } - - return &ThreatAnalysisResponse{ - SightingCount: len(data.Sightings), - ActiveAgents: extractActiveAgents(data.Sightings), - ThreatAssessment: assessment, - Recommendations: generateRecommendations(len(data.Sightings)), - }, nil + query := dgraph.NewQuery(` + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } + } + `).WithVariable("$since", since) + + resp, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } + + var data SightingsData + if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { + return nil, err + } + + assessment, err := generateThreatAssessment(data.Sightings) + if err != nil { + return nil, err + } + + return &ThreatAnalysisResponse{ + SightingCount: len(data.Sightings), + ActiveAgents: extractActiveAgents(data.Sightings), + ThreatAssessment: assessment, + Recommendations: generateRecommendations(len(data.Sightings)), + }, nil } func generateThreatAssessment(sightings []AgentSighting) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } - - prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." - data, err := json.Marshal(sightings) - if err != nil { - return "", err - } - - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage("Agent surveillance data: "+string(data)), - ) - if err != nil { - return "", err - } - input.Temperature = 0.4 - - out, err := model.Invoke(input) - if err != nil { - return "", err - } - - return strings.TrimSpace(out.Choices[0].Message.Content), nil + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } + + prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + data, err := json.Marshal(sightings) + if err != nil { + return "", err + } + + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage("Agent surveillance data: "+string(data)), + ) + if err != nil { + return "", err + } + input.Temperature = 0.4 + + out, err := model.Invoke(input) + if err != nil { + return "", err + } + + return strings.TrimSpace(out.Choices[0].Message.Content), nil } func extractActiveAgents(sightings []AgentSighting) []string { - seen := map[string]struct{}{} - var agents []string - for _, s := range sightings { - if _, ok := seen[s.AgentName]; !ok { - seen[s.AgentName] = struct{}{} - agents = append(agents, s.AgentName) - } - } - return agents + seen := map[string]struct{}{} + var agents []string + for _, s := range sightings { + if _, ok := seen[s.AgentName]; !ok { + seen[s.AgentName] = struct{}{} + agents = append(agents, s.AgentName) + } + } + return agents } func generateRecommendations(count int) []string { - switch { - case count > 5: - return []string{ - "Implement additional security measures.", - "Enhance threat detection capabilities.", - "Implement enhanced access control.", - } - case count > 2: - return []string{ - "Enhance threat detection capabilities.", - "Implement enhanced access control.", - } - default: - return []string{"Implement additional security measures."} - } + switch { + case count > 5: + return []string{ + "Implement additional security measures.", + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + case count > 2: + return []string{ + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + default: + return []string{"Implement additional security measures."} + } } ``` @@ -338,38 +336,43 @@ data arrives. We'll deploy persistent surveillance agents and upgrade our import function to trigger them: ```go +import ( + "time" + "github.com/hypermodeinc/modus/sdk/go/pkg/agents" +) + type SurveillanceAgent struct { - agents.AgentBase - MonitoredSectors []string `json:"monitored_sectors"` - SightingsTracked int `json:"sightings_tracked"` - RecentActivities []string `json:"recent_activities"` - LastSweepTime time.Time `json:"last_sweep_time"` + agents.AgentBase + MonitoredSectors []string `json:"monitored_sectors"` + SightingsTracked int `json:"sightings_tracked"` + RecentActivities []string `json:"recent_activities"` + LastSweepTime time.Time `json:"last_sweep_time"` } func (s *SurveillanceAgent) Name() string { - return "SurveillanceAgent" + return "SurveillanceAgent" } func (s *SurveillanceAgent) OnInitialize() error { - s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} - s.SightingsTracked = 0 - s.RecentActivities = []string{} - s.LastSweepTime = time.Now() - return nil + s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} + s.SightingsTracked = 0 + s.RecentActivities = []string{} + s.LastSweepTime = time.Now() + return nil } func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { - switch msgName { - case "continuous_surveillance": - return s.processNewIntelligence() - case "get_status": - return s.getOperationalStatus() - } - return nil, fmt.Errorf("unrecognized directive: %s", msgName) + switch msgName { + case "continuous_surveillance": + return s.processNewIntelligence() + case "get_status": + return s.getOperationalStatus() + } + return nil, fmt.Errorf("unrecognized directive: %s", msgName) } func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { - query := dgraph.NewQuery(` + query := dgraph.NewQuery(` query getRecentSightings($since: string) { sightings(func: ge(timestamp, $since)) { agent_name @@ -379,64 +382,64 @@ func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { } `).WithVariable("$since", s.LastSweepTime.Format(time.RFC3339)) - _, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } + _, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } - s.LastSweepTime = time.Now() - s.SightingsTracked++ - activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) - s.RecentActivities = append(s.RecentActivities, activity) + s.LastSweepTime = time.Now() + s.SightingsTracked++ + activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) + s.RecentActivities = append(s.RecentActivities, activity) - if len(s.RecentActivities) > 3 { - s.RecentActivities = s.RecentActivities[1:] - } + if len(s.RecentActivities) > 3 { + s.RecentActivities = s.RecentActivities[1:] + } - result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) - return &result, nil + result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) + return &result, nil } func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { - status := fmt.Sprintf(`Surveillance Agent Status: + status := fmt.Sprintf(`Surveillance Agent Status: - Operational: Active - Monitoring %d sectors: %s - Last sweep: %s - Tracking %d ongoing sightings - Recent activities: %s`, - len(s.MonitoredSectors), - strings.Join(s.MonitoredSectors, ", "), - s.LastSweepTime.Format("2006-01-02 15:04:05"), - s.SightingsTracked, - strings.Join(s.RecentActivities, ", "), - ) - return &status, nil + len(s.MonitoredSectors), + strings.Join(s.MonitoredSectors, ", "), + s.LastSweepTime.Format("2006-01-02 15:04:05"), + s.SightingsTracked, + strings.Join(s.RecentActivities, ", "), + ) + return &status, nil } func (s *SurveillanceAgent) GetState() *string { return nil } func (s *SurveillanceAgent) SetState(state *string) {} func init() { - agents.Register(&SurveillanceAgent{}) + agents.Register(&SurveillanceAgent{}) } func DeploySurveillanceAgent() (string, error) { - agentInfo, err := agents.Start("SurveillanceAgent") - if err != nil { - return "", err - } - return agentInfo.Name + " - " + agentInfo.Id, nil + agentInfo, err := agents.Start("SurveillanceAgent") + if err != nil { + return "", err + } + return agentInfo.Name + " - " + agentInfo.Id, nil } func GetSurveillanceStatus(agentId string) (string, error) { - result, err := agents.SendMessage(agentId, "get_status") - if err != nil { - return "", err - } - if result == nil { - return "", fmt.Errorf("no response from agent") - } - return *result, nil + result, err := agents.SendMessage(agentId, "get_status") + if err != nil { + return "", err + } + if result == nil { + return "", fmt.Errorf("no response from agent") + } + return *result, nil } ``` @@ -445,30 +448,30 @@ surveillance: ```go func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, error) { - analysis, err := analyzeAgentWithAI(s.Behavior) - if err != nil { - return nil, err - } - s.AiAnalysis = &analysis - - data, err := json.Marshal(s) - if err != nil { - return nil, err - } - - mutation := dgraph.NewMutation().WithSetJson(string(data)) - if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { - return nil, err - } - - if surveillanceAgentId != nil { - if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { - return nil, err - } - } - - res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) - return &res, nil + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis + + data, err := json.Marshal(s) + if err != nil { + return nil, err + } + + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } + + if surveillanceAgentId != nil { + if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { + return nil, err + } + } + + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil } ``` From 068e3a5e8a589d368b0cee31f64ce0d9f0526060 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 16:55:11 -0700 Subject: [PATCH 07/15] fix: add assemblyscript port for knowledge graphs --- modus/knowledge-graphs.mdx | 553 ++++++++++++++++++++++--------------- 1 file changed, 336 insertions(+), 217 deletions(-) diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 347571d9..24551e3c 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -83,7 +83,8 @@ behavior in the simulated reality. The system needs to: When new Agent activity is detected in the Matrix, you need to process it quickly. This is perfect for a stateless function: -```go + +```go got package main import ( @@ -91,76 +92,103 @@ import ( "fmt" "strings" - "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" - "github.com/hypermodeinc/modus/sdk/go/pkg/models" - "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" -) +"github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" +"github.com/hypermodeinc/modus/sdk/go/pkg/models" +"github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" ) -type AgentSighting struct { - SightingID string `json:"sighting_id"` - AgentName string `json:"agent_name"` - Location string `json:"location"` - Behavior string `json:"behavior"` - ThreatLevel int `json:"threat_level"` - Timestamp string `json:"timestamp"` - AiAnalysis *string `json:"ai_analysis,omitempty"` -} +type AgentSighting struct { SightingID string `json:"sighting_id"` AgentName +string `json:"agent_name"` Location string `json:"location"` Behavior string +`json:"behavior"` ThreatLevel int `json:"threat_level"` Timestamp string +`json:"timestamp"` AiAnalysis \*string `json:"ai_analysis,omitempty"` } + +type ThreatAnalysisResponse struct { SightingCount int `json:"sighting_count"` +ActiveAgents []string `json:"active_agents"` ThreatAssessment string +`json:"threat_assessment"` Recommendations []string `json:"recommendations"` } + +type SightingsData struct { Sightings []AgentSighting `json:"sightings"` } + +func ImportAgentSighting(s AgentSighting) (\*string, error) { analysis, err := +analyzeAgentWithAI(s.Behavior) if err != nil { return nil, err } s.AiAnalysis = +&analysis + +data, err := json.Marshal(s) if err != nil { return nil, err } + +mutation := dgraph.NewMutation().WithSetJson(string(data)) if \_, err := +dgraph.ExecuteMutations("dgraph", mutation); err != nil { return nil, err } + +res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) return &res, +nil } + +func analyzeAgentWithAI(behavior string) (string, error) { model, err := +models.GetModel[openai.ChatModel]("text-generator") if err != nil { return "", +err } -type ThreatAnalysisResponse struct { - SightingCount int `json:"sighting_count"` - ActiveAgents []string `json:"active_agents"` - ThreatAssessment string `json:"threat_assessment"` - Recommendations []string `json:"recommendations"` +prompt := "Analyze this Agent behavior pattern and assess threat level, +behavioral changes, and tactical implications for resistance operations. Respond +with no more than 3 short sentences." input, err := model.CreateInput( +openai.NewSystemMessage(prompt), openai.NewUserMessage(behavior), ) if err != +nil { return "", err } input.Temperature = 0.3 + +out, err := model.Invoke(input) if err != nil { return "", err } return +strings.TrimSpace(out.Choices[0].Message.Content), nil } + +```` +```typescript AssemblyScript +import { Agent, agents, dgraph, models } from "@hypermode/modus-sdk-as"; +import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; +import { JSON } from "json-as"; + +@json +class AgentSighting { + sighting_id!: string; + agent_name!: string; + location!: string; + behavior!: string; + timestamp!: string; + @omitnull() + ai_analysis: string | null = null; } -type SightingsData struct { - Sightings []AgentSighting `json:"sightings"` +@json +class ThreatAnalysisResponse { + sightings_count!: i32; + active_agents!: string[]; + threat_assessment!: string; + reccommendations!: string[]; } -func ImportAgentSighting(s AgentSighting) (*string, error) { - analysis, err := analyzeAgentWithAI(s.Behavior) - if err != nil { - return nil, err - } - s.AiAnalysis = &analysis +@json +class SightingsData { + sightings!: AgentSighting[] +} - data, err := json.Marshal(s) - if err != nil { - return nil, err - } +export function importAgentSighting(s: AgentSighting): string { + const analysis = analyzeAgentWithAI(s.behavior); + s.ai_analysis = analysis; - mutation := dgraph.NewMutation().WithSetJson(string(data)) - if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { - return nil, err - } + const mutation = new dgraph.Mutation(JSON.stringify(s)); + dgraph.executeMutations("dgraph", mutation); - res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) - return &res, nil + return "Agent sighting processed " + s.sighting_id; } -func analyzeAgentWithAI(behavior string) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } +function analyzeAgentWithAI(behavior: string): string { + const model = models.getModel("text-generator"); - prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(behavior), - ) - if err != nil { - return "", err - } - input.Temperature = 0.3 + const prompt = "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences."; - out, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(out.Choices[0].Message.Content), nil + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(behavior) + ]); + input.temperature = 0.3; + + const out = model.invoke(input); + return out.choices[0].message.content.trim(); } -``` +```` + + Now let's deploy this data import function and test it: @@ -196,7 +224,8 @@ mutation { Now that we've got the Agent sighting data in our knowledge graph, let's analyze the broader threat landscape: -```go + +```go Go func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { query := dgraph.NewQuery(` query analyzeAgents($since: string) { @@ -212,88 +241,117 @@ func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { } `).WithVariable("$since", since) - resp, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } +resp, err := dgraph.ExecuteQuery("dgraph", query) if err != nil { return nil, +err } - var data SightingsData - if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { - return nil, err - } +var data SightingsData if err := json.Unmarshal([]byte(resp.Json), &data); err +!= nil { return nil, err } - assessment, err := generateThreatAssessment(data.Sightings) - if err != nil { - return nil, err - } +assessment, err := generateThreatAssessment(data.Sightings) if err != nil { +return nil, err } - return &ThreatAnalysisResponse{ - SightingCount: len(data.Sightings), - ActiveAgents: extractActiveAgents(data.Sightings), - ThreatAssessment: assessment, - Recommendations: generateRecommendations(len(data.Sightings)), - }, nil -} +return &ThreatAnalysisResponse{ SightingCount: len(data.Sightings), +ActiveAgents: extractActiveAgents(data.Sightings), ThreatAssessment: assessment, +Recommendations: generateRecommendations(len(data.Sightings)), }, nil } func generateThreatAssessment(sightings []AgentSighting) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } +model, err := models.GetModel[openai.ChatModel]("text-generator") if err != nil +{ return "", err } - prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." - data, err := json.Marshal(sightings) - if err != nil { - return "", err - } +prompt := "Based on these Agent sightings, provide a strategic threat assessment +focusing on behavioral patterns and risks to resistance operations. Respond with +no more than 2 short sentences." data, err := json.Marshal(sightings) if err != +nil { return "", err } - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage("Agent surveillance data: "+string(data)), - ) - if err != nil { - return "", err - } - input.Temperature = 0.4 +input, err := model.CreateInput( openai.NewSystemMessage(prompt), +openai.NewUserMessage("Agent surveillance data: "+string(data)), ) if err != nil +{ return "", err } input.Temperature = 0.4 - out, err := model.Invoke(input) - if err != nil { - return "", err - } +out, err := model.Invoke(input) if err != nil { return "", err } + +return strings.TrimSpace(out.Choices[0].Message.Content), nil } + +func extractActiveAgents(sightings []AgentSighting) []string { seen := +map[string]struct{}{} var agents []string for _, s := range sightings { if _, ok +:= seen[s.AgentName]; !ok { seen[s.AgentName] = struct{}{} agents = +append(agents, s.AgentName) } } return agents } + +func generateRecommendations(count int) []string { switch { case count > 5: +return []string{ "Implement additional security measures.", "Enhance threat +detection capabilities.", "Implement enhanced access control.", } case count > +2: return []string{ "Enhance threat detection capabilities.", "Implement +enhanced access control.", } default: return []string{"Implement additional +security measures."} } } + +```` +```typescript AssemblyScript +export function analyzeAgentPatterns(since: string): ThreatAnalysisResponse { + const query = new dgraph.Query(` + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } + } + `).withVariable("since", since); + + const resp = dgraph.executeQuery("dgraph", query); + + const data = JSON.parse(resp.Json); - return strings.TrimSpace(out.Choices[0].Message.Content), nil + const assessment = generateThreatAssessment(data.sightings); + + return { + sightings_count: data.sightings.length, + active_agents: extractActiveAgents(data.sightings), + threat_assessment: assessment, + reccommendations: generateRecommendations(data.sightings.length) + }; } -func extractActiveAgents(sightings []AgentSighting) []string { - seen := map[string]struct{}{} - var agents []string - for _, s := range sightings { - if _, ok := seen[s.AgentName]; !ok { - seen[s.AgentName] = struct{}{} - agents = append(agents, s.AgentName) - } - } - return agents +function generateThreatAssessment(sightings: AgentSighting[]): string { + const model = models.getModel("text-generator"); + + const prompt = "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(JSON.stringify(sightings)) + ]); + input.temperature = 0.4; + + const out = model.invoke(input); + return out.choices[0].message.content.trim(); +} + +function extractActiveAgents(sightings: AgentSighting[]): string[] { + return sightings.map(s => s.agent_name); } -func generateRecommendations(count int) []string { - switch { - case count > 5: - return []string{ +function generateRecommendations(count: i32): string[] { + if (count > 5) { + return [ "Implement additional security measures.", "Enhance threat detection capabilities.", "Implement enhanced access control.", - } - case count > 2: - return []string{ + ]; + } else if (count > 2) { + return [ "Enhance threat detection capabilities.", "Implement enhanced access control.", - } - default: - return []string{"Implement additional security measures."} + ] + } else { + return [ + "Implement additional security measures." + ] } } -``` +```` Let's query our surveillance data: @@ -335,118 +393,171 @@ Now let's enhance our system to automatically coordinate surveillance when new data arrives. We'll deploy persistent surveillance agents and upgrade our import function to trigger them: -```go + +```go Go import ( "time" "github.com/hypermodeinc/modus/sdk/go/pkg/agents" ) -type SurveillanceAgent struct { - agents.AgentBase - MonitoredSectors []string `json:"monitored_sectors"` - SightingsTracked int `json:"sightings_tracked"` - RecentActivities []string `json:"recent_activities"` - LastSweepTime time.Time `json:"last_sweep_time"` -} +type SurveillanceAgent struct { agents.AgentBase MonitoredSectors []string +`json:"monitored_sectors"` SightingsTracked int `json:"sightings_tracked"` +RecentActivities []string `json:"recent_activities"` LastSweepTime time.Time +`json:"last_sweep_time"` } -func (s *SurveillanceAgent) Name() string { - return "SurveillanceAgent" -} +func (s \*SurveillanceAgent) Name() string { return "SurveillanceAgent" } -func (s *SurveillanceAgent) OnInitialize() error { - s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} - s.SightingsTracked = 0 - s.RecentActivities = []string{} - s.LastSweepTime = time.Now() - return nil -} +func (s \*SurveillanceAgent) OnInitialize() error { s.MonitoredSectors = +[]string{"Downtown Loop", "Megacity Financial", "Industrial District"} +s.SightingsTracked = 0 s.RecentActivities = []string{} s.LastSweepTime = +time.Now() return nil } -func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { - switch msgName { - case "continuous_surveillance": - return s.processNewIntelligence() - case "get_status": - return s.getOperationalStatus() - } - return nil, fmt.Errorf("unrecognized directive: %s", msgName) -} +func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) +(\*string, error) { switch msgName { case "continuous_surveillance": return +s.processNewIntelligence() case "get_status": return s.getOperationalStatus() } +return nil, fmt.Errorf("unrecognized directive: %s", msgName) } -func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { - query := dgraph.NewQuery(` - query getRecentSightings($since: string) { - sightings(func: ge(timestamp, $since)) { - agent_name - threat_level - location - } - } - `).WithVariable("$since", s.LastSweepTime.Format(time.RFC3339)) +func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { query := +dgraph.NewQuery(` query getRecentSightings($since: string) { sightings(func: ge(timestamp, $since)) { agent_name threat_level location } } `).WithVariable("$since", +s.LastSweepTime.Format(time.RFC3339)) - _, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } +\_, err := dgraph.ExecuteQuery("dgraph", query) if err != nil { return nil, err +} - s.LastSweepTime = time.Now() - s.SightingsTracked++ - activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) - s.RecentActivities = append(s.RecentActivities, activity) +s.LastSweepTime = time.Now() s.SightingsTracked++ activity := fmt.Sprintf("Auto +surveillance at %s", s.LastSweepTime.Format("15:04:05")) s.RecentActivities = +append(s.RecentActivities, activity) - if len(s.RecentActivities) > 3 { - s.RecentActivities = s.RecentActivities[1:] - } +if len(s.RecentActivities) > 3 { s.RecentActivities = s.RecentActivities[1:] } - result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) - return &result, nil -} +result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. +Matrix integrity: COMPROMISED", s.SightingsTracked) return &result, nil } + +func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { status := +fmt.Sprintf(`Surveillance Agent Status: -func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { - status := fmt.Sprintf(`Surveillance Agent Status: - Operational: Active - Monitoring %d sectors: %s - Last sweep: %s - Tracking %d ongoing sightings -- Recent activities: %s`, - len(s.MonitoredSectors), - strings.Join(s.MonitoredSectors, ", "), - s.LastSweepTime.Format("2006-01-02 15:04:05"), - s.SightingsTracked, - strings.Join(s.RecentActivities, ", "), - ) - return &status, nil -} +- Recent activities: %s`, len(s.MonitoredSectors), + strings.Join(s.MonitoredSectors, ", "), s.LastSweepTime.Format("2006-01-02 + 15:04:05"), s.SightingsTracked, strings.Join(s.RecentActivities, ", "), ) + return &status, nil } -func (s *SurveillanceAgent) GetState() *string { return nil } -func (s *SurveillanceAgent) SetState(state *string) {} +func (s *SurveillanceAgent) GetState() *string { return nil } func (s +*SurveillanceAgent) SetState(state *string) {} -func init() { - agents.Register(&SurveillanceAgent{}) -} +func init() { agents.Register(&SurveillanceAgent{}) } -func DeploySurveillanceAgent() (string, error) { - agentInfo, err := agents.Start("SurveillanceAgent") - if err != nil { - return "", err +func DeploySurveillanceAgent() (string, error) { agentInfo, err := +agents.Start("SurveillanceAgent") if err != nil { return "", err } return +agentInfo.Name + " - " + agentInfo.Id, nil } + +func GetSurveillanceStatus(agentId string) (string, error) { result, err := +agents.SendMessage(agentId, "get_status") if err != nil { return "", err } if +result == nil { return "", fmt.Errorf("no response from agent") } return +\*result, nil } + +```` +```typescript AssemblyScript +class SurveillanceAgent extends Agent { + private monitoredSectors: string[] = []; + private sightingsTracked: i32 = 0; + private recentActivities: string[] = []; + private lastSweepTime: Date = new Date(0); + + get name(): string { + return "SurveillanceAgent"; } - return agentInfo.Name + " - " + agentInfo.Id, nil -} -func GetSurveillanceStatus(agentId string) (string, error) { - result, err := agents.SendMessage(agentId, "get_status") - if err != nil { - return "", err + onInitialize(): void { + this.monitoredSectors = ["Downtown Loop", "Megacity Financial", "Industrial District"]; + this.lastSweepTime = new Date(Date.now()); + } + + onReceiveMessage(msgName: string, data: string | null): string { + if (msgName === "continuous_surveillance") { + return this.processNewIntelligence(); + } else if (msgName === "get_status") { + return this.getOperationalStatus(); + } + throw new Error("Unrecognized directive: " + msgName); + } + + private processNewIntelligence(): string { + const query = new dgraph.Query(` + query getRecentSightings($since: string) { + sightings(func: ge(timestamp, $since)) { + agent_name + threat_level + location + } + } + `).withVariable("since", this.lastSweepTime.toISOString()); + + dgraph.executeQuery("dgraph", query); + + this.lastSweepTime = new Date(Date.now()); + this.sightingsTracked++; + + const activity = "Auto surveillance at " + this.lastSweepTime.toTimeString(); + this.recentActivities.push(activity); + + if (this.recentActivities.length > 3) { + this.recentActivities.shift(); + } + + return `Data processed automatically.\nTracking ${this.sightingsTracked} sightings. Matrix integrity: COMPROMISED`; + } + + private getOperationalStatus(): string { + return `Surveillance Agent Status: +- Operational: Active +- Monitoring ${this.monitoredSectors.length.toString()} sectors: ${this.monitoredSectors.join(", ")} +- Last sweep: ${this.lastSweepTime.toISOString().replace("T", " ").slice(0, 19)} +- Tracking ${this.sightingsTracked.toString()} ongoing sightings +- Recent activities: ${this.recentActivities.join(", ")}`; + } + + getState(): string { + return "" + // return JSON.stringify(this); } - if result == nil { - return "", fmt.Errorf("no response from agent") + + setState(data: string | null): void { + // if (!data) return; + // const state = JSON.parse(data); + // this.monitoredSectors = state.monitoredSectors; + // this.sightingsTracked = state.sightingsTracked; + // this.recentActivities = state.recentActivities; + // this.lastSweepTime = state.lastSweepTime; } - return *result, nil } -``` + +agents.register(); + +export function deploySurveillanceAgent(): string { + const agentInfo = agents.start("SurveillanceAgent"); + return `${agentInfo.name} - ${agentInfo.id}`; +} + +export function getSurveillanceStatus(agentId: string): string { + const result = agents.sendMessage(agentId, "get_status"); + if (result == null) { + throw new Error("No response from agent"); + } + return result; +} +```` + + Now let's enhance our original import function to automatically trigger surveillance: -```go + +```go Go func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, error) { analysis, err := analyzeAgentWithAI(s.Behavior) if err != nil { @@ -454,26 +565,34 @@ func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, } s.AiAnalysis = &analysis - data, err := json.Marshal(s) - if err != nil { - return nil, err - } +data, err := json.Marshal(s) if err != nil { return nil, err } - mutation := dgraph.NewMutation().WithSetJson(string(data)) - if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { - return nil, err - } +mutation := dgraph.NewMutation().WithSetJson(string(data)) if \_, err := +dgraph.ExecuteMutations("dgraph", mutation); err != nil { return nil, err } - if surveillanceAgentId != nil { - if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { - return nil, err - } +if surveillanceAgentId != nil { if err := +agents.SendMessageAsync(\*surveillanceAgentId, "continuous_surveillance"); err +!= nil { return nil, err } } + +res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) return &res, +nil } + +```` +```typescript AssemblyScript +export function importAgentSighting(s: AgentSighting, surveilanceAgentId: string | null = null): string { + const analysis = analyzeAgentWithAI(s.behavior); + s.ai_analysis = analysis; + + const mutation = new dgraph.Mutation(JSON.stringify(s)); + dgraph.executeMutations("dgraph", mutation); + + if (surveilanceAgentId) { + agents.sendMessageAsync(surveilanceAgentId, "continuous_surveillance"); } - res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) - return &res, nil + return "Agent sighting processed " + s.sighting_id; } -``` +```` Deploy your surveillance agent: From c90705eac55c25c115fd9195987c662d33d73586 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 16:58:51 -0700 Subject: [PATCH 08/15] fix: remove stupid trunk formatting --- modus/knowledge-graphs.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 24551e3c..1b63654c 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -84,7 +84,7 @@ When new Agent activity is detected in the Matrix, you need to process it quickly. This is perfect for a stateless function: -```go got +```go Go package main import ( @@ -353,6 +353,8 @@ function generateRecommendations(count: i32): string[] { } ```` + + Let's query our surveillance data: ```graphql @@ -594,6 +596,8 @@ export function importAgentSighting(s: AgentSighting, surveilanceAgentId: string } ```` + + Deploy your surveillance agent: ```graphql From fe4ec7afc1e65f5eb8b9551bc84d6ddbec19ccdc Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 17:00:31 -0700 Subject: [PATCH 09/15] argh this trunk From f98baf3e96a504d4fe000ff3b2b49a32cdf13564 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 17:00:55 -0700 Subject: [PATCH 10/15] try to disable trunk From b16848cce066c467cdda92060629a643158583c4 Mon Sep 17 00:00:00 2001 From: JairusSW Date: Tue, 8 Jul 2025 17:01:05 -0700 Subject: [PATCH 11/15] try to disable trunk --- modus/knowledge-graphs.mdx | 364 ++++++++++++++++++++++++------------- 1 file changed, 238 insertions(+), 126 deletions(-) diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 1b63654c..269bf248 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -92,47 +92,76 @@ import ( "fmt" "strings" -"github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" -"github.com/hypermodeinc/modus/sdk/go/pkg/models" -"github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" ) - -type AgentSighting struct { SightingID string `json:"sighting_id"` AgentName -string `json:"agent_name"` Location string `json:"location"` Behavior string -`json:"behavior"` ThreatLevel int `json:"threat_level"` Timestamp string -`json:"timestamp"` AiAnalysis \*string `json:"ai_analysis,omitempty"` } + "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" +) -type ThreatAnalysisResponse struct { SightingCount int `json:"sighting_count"` -ActiveAgents []string `json:"active_agents"` ThreatAssessment string -`json:"threat_assessment"` Recommendations []string `json:"recommendations"` } +type AgentSighting struct { + SightingID string `json:"sighting_id"` + AgentName string `json:"agent_name"` + Location string `json:"location"` + Behavior string `json:"behavior"` + ThreatLevel int `json:"threat_level"` + Timestamp string `json:"timestamp"` + AiAnalysis *string `json:"ai_analysis,omitempty"` +} -type SightingsData struct { Sightings []AgentSighting `json:"sightings"` } +type ThreatAnalysisResponse struct { + SightingCount int `json:"sighting_count"` + ActiveAgents []string `json:"active_agents"` + ThreatAssessment string `json:"threat_assessment"` + Recommendations []string `json:"recommendations"` +} -func ImportAgentSighting(s AgentSighting) (\*string, error) { analysis, err := -analyzeAgentWithAI(s.Behavior) if err != nil { return nil, err } s.AiAnalysis = -&analysis +type SightingsData struct { + Sightings []AgentSighting `json:"sightings"` +} -data, err := json.Marshal(s) if err != nil { return nil, err } +func ImportAgentSighting(s AgentSighting) (*string, error) { + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis -mutation := dgraph.NewMutation().WithSetJson(string(data)) if \_, err := -dgraph.ExecuteMutations("dgraph", mutation); err != nil { return nil, err } + data, err := json.Marshal(s) + if err != nil { + return nil, err + } -res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) return &res, -nil } + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } -func analyzeAgentWithAI(behavior string) (string, error) { model, err := -models.GetModel[openai.ChatModel]("text-generator") if err != nil { return "", -err } + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil +} -prompt := "Analyze this Agent behavior pattern and assess threat level, -behavioral changes, and tactical implications for resistance operations. Respond -with no more than 3 short sentences." input, err := model.CreateInput( -openai.NewSystemMessage(prompt), openai.NewUserMessage(behavior), ) if err != -nil { return "", err } input.Temperature = 0.3 +func analyzeAgentWithAI(behavior string) (string, error) { + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } -out, err := model.Invoke(input) if err != nil { return "", err } return -strings.TrimSpace(out.Choices[0].Message.Content), nil } + prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage(behavior), + ) + if err != nil { + return "", err + } + input.Temperature = 0.3 -```` + out, err := model.Invoke(input) + if err != nil { + return "", err + } + return strings.TrimSpace(out.Choices[0].Message.Content), nil +} +``` ```typescript AssemblyScript import { Agent, agents, dgraph, models } from "@hypermode/modus-sdk-as"; import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; @@ -186,8 +215,7 @@ function analyzeAgentWithAI(behavior: string): string { const out = model.invoke(input); return out.choices[0].message.content.trim(); } -```` - +``` Now let's deploy this data import function and test it: @@ -241,49 +269,88 @@ func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { } `).WithVariable("$since", since) -resp, err := dgraph.ExecuteQuery("dgraph", query) if err != nil { return nil, -err } + resp, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } -var data SightingsData if err := json.Unmarshal([]byte(resp.Json), &data); err -!= nil { return nil, err } + var data SightingsData + if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { + return nil, err + } -assessment, err := generateThreatAssessment(data.Sightings) if err != nil { -return nil, err } + assessment, err := generateThreatAssessment(data.Sightings) + if err != nil { + return nil, err + } -return &ThreatAnalysisResponse{ SightingCount: len(data.Sightings), -ActiveAgents: extractActiveAgents(data.Sightings), ThreatAssessment: assessment, -Recommendations: generateRecommendations(len(data.Sightings)), }, nil } + return &ThreatAnalysisResponse{ + SightingCount: len(data.Sightings), + ActiveAgents: extractActiveAgents(data.Sightings), + ThreatAssessment: assessment, + Recommendations: generateRecommendations(len(data.Sightings)), + }, nil +} func generateThreatAssessment(sightings []AgentSighting) (string, error) { -model, err := models.GetModel[openai.ChatModel]("text-generator") if err != nil -{ return "", err } - -prompt := "Based on these Agent sightings, provide a strategic threat assessment -focusing on behavioral patterns and risks to resistance operations. Respond with -no more than 2 short sentences." data, err := json.Marshal(sightings) if err != -nil { return "", err } + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } -input, err := model.CreateInput( openai.NewSystemMessage(prompt), -openai.NewUserMessage("Agent surveillance data: "+string(data)), ) if err != nil -{ return "", err } input.Temperature = 0.4 + prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + data, err := json.Marshal(sightings) + if err != nil { + return "", err + } -out, err := model.Invoke(input) if err != nil { return "", err } + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage("Agent surveillance data: "+string(data)), + ) + if err != nil { + return "", err + } + input.Temperature = 0.4 -return strings.TrimSpace(out.Choices[0].Message.Content), nil } + out, err := model.Invoke(input) + if err != nil { + return "", err + } -func extractActiveAgents(sightings []AgentSighting) []string { seen := -map[string]struct{}{} var agents []string for _, s := range sightings { if _, ok -:= seen[s.AgentName]; !ok { seen[s.AgentName] = struct{}{} agents = -append(agents, s.AgentName) } } return agents } + return strings.TrimSpace(out.Choices[0].Message.Content), nil +} -func generateRecommendations(count int) []string { switch { case count > 5: -return []string{ "Implement additional security measures.", "Enhance threat -detection capabilities.", "Implement enhanced access control.", } case count > -2: return []string{ "Enhance threat detection capabilities.", "Implement -enhanced access control.", } default: return []string{"Implement additional -security measures."} } } +func extractActiveAgents(sightings []AgentSighting) []string { + seen := map[string]struct{}{} + var agents []string + for _, s := range sightings { + if _, ok := seen[s.AgentName]; !ok { + seen[s.AgentName] = struct{}{} + agents = append(agents, s.AgentName) + } + } + return agents +} -```` +func generateRecommendations(count int) []string { + switch { + case count > 5: + return []string{ + "Implement additional security measures.", + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + case count > 2: + return []string{ + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + default: + return []string{"Implement additional security measures."} + } +} +``` ```typescript AssemblyScript export function analyzeAgentPatterns(since: string): ThreatAnalysisResponse { const query = new dgraph.Query(` @@ -351,8 +418,7 @@ function generateRecommendations(count: i32): string[] { ] } } -```` - +``` Let's query our surveillance data: @@ -402,66 +468,107 @@ import ( "github.com/hypermodeinc/modus/sdk/go/pkg/agents" ) -type SurveillanceAgent struct { agents.AgentBase MonitoredSectors []string -`json:"monitored_sectors"` SightingsTracked int `json:"sightings_tracked"` -RecentActivities []string `json:"recent_activities"` LastSweepTime time.Time -`json:"last_sweep_time"` } - -func (s \*SurveillanceAgent) Name() string { return "SurveillanceAgent" } - -func (s \*SurveillanceAgent) OnInitialize() error { s.MonitoredSectors = -[]string{"Downtown Loop", "Megacity Financial", "Industrial District"} -s.SightingsTracked = 0 s.RecentActivities = []string{} s.LastSweepTime = -time.Now() return nil } +type SurveillanceAgent struct { + agents.AgentBase + MonitoredSectors []string `json:"monitored_sectors"` + SightingsTracked int `json:"sightings_tracked"` + RecentActivities []string `json:"recent_activities"` + LastSweepTime time.Time `json:"last_sweep_time"` +} -func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) -(\*string, error) { switch msgName { case "continuous_surveillance": return -s.processNewIntelligence() case "get_status": return s.getOperationalStatus() } -return nil, fmt.Errorf("unrecognized directive: %s", msgName) } +func (s *SurveillanceAgent) Name() string { + return "SurveillanceAgent" +} -func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { query := -dgraph.NewQuery(` query getRecentSightings($since: string) { sightings(func: ge(timestamp, $since)) { agent_name threat_level location } } `).WithVariable("$since", -s.LastSweepTime.Format(time.RFC3339)) +func (s *SurveillanceAgent) OnInitialize() error { + s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} + s.SightingsTracked = 0 + s.RecentActivities = []string{} + s.LastSweepTime = time.Now() + return nil +} -\_, err := dgraph.ExecuteQuery("dgraph", query) if err != nil { return nil, err +func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { + switch msgName { + case "continuous_surveillance": + return s.processNewIntelligence() + case "get_status": + return s.getOperationalStatus() + } + return nil, fmt.Errorf("unrecognized directive: %s", msgName) } -s.LastSweepTime = time.Now() s.SightingsTracked++ activity := fmt.Sprintf("Auto -surveillance at %s", s.LastSweepTime.Format("15:04:05")) s.RecentActivities = -append(s.RecentActivities, activity) +func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { + query := dgraph.NewQuery(` + query getRecentSightings($since: string) { + sightings(func: ge(timestamp, $since)) { + agent_name + threat_level + location + } + } + `).WithVariable("$since", s.LastSweepTime.Format(time.RFC3339)) -if len(s.RecentActivities) > 3 { s.RecentActivities = s.RecentActivities[1:] } + _, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } + + s.LastSweepTime = time.Now() + s.SightingsTracked++ + activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) + s.RecentActivities = append(s.RecentActivities, activity) -result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. -Matrix integrity: COMPROMISED", s.SightingsTracked) return &result, nil } + if len(s.RecentActivities) > 3 { + s.RecentActivities = s.RecentActivities[1:] + } -func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { status := -fmt.Sprintf(`Surveillance Agent Status: + result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) + return &result, nil +} +func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { + status := fmt.Sprintf(`Surveillance Agent Status: - Operational: Active - Monitoring %d sectors: %s - Last sweep: %s - Tracking %d ongoing sightings -- Recent activities: %s`, len(s.MonitoredSectors), - strings.Join(s.MonitoredSectors, ", "), s.LastSweepTime.Format("2006-01-02 - 15:04:05"), s.SightingsTracked, strings.Join(s.RecentActivities, ", "), ) - return &status, nil } - -func (s *SurveillanceAgent) GetState() *string { return nil } func (s -*SurveillanceAgent) SetState(state *string) {} +- Recent activities: %s`, + len(s.MonitoredSectors), + strings.Join(s.MonitoredSectors, ", "), + s.LastSweepTime.Format("2006-01-02 15:04:05"), + s.SightingsTracked, + strings.Join(s.RecentActivities, ", "), + ) + return &status, nil +} -func init() { agents.Register(&SurveillanceAgent{}) } +func (s *SurveillanceAgent) GetState() *string { return nil } +func (s *SurveillanceAgent) SetState(state *string) {} -func DeploySurveillanceAgent() (string, error) { agentInfo, err := -agents.Start("SurveillanceAgent") if err != nil { return "", err } return -agentInfo.Name + " - " + agentInfo.Id, nil } +func init() { + agents.Register(&SurveillanceAgent{}) +} -func GetSurveillanceStatus(agentId string) (string, error) { result, err := -agents.SendMessage(agentId, "get_status") if err != nil { return "", err } if -result == nil { return "", fmt.Errorf("no response from agent") } return -\*result, nil } +func DeploySurveillanceAgent() (string, error) { + agentInfo, err := agents.Start("SurveillanceAgent") + if err != nil { + return "", err + } + return agentInfo.Name + " - " + agentInfo.Id, nil +} -```` +func GetSurveillanceStatus(agentId string) (string, error) { + result, err := agents.SendMessage(agentId, "get_status") + if err != nil { + return "", err + } + if result == nil { + return "", fmt.Errorf("no response from agent") + } + return *result, nil +} +``` ```typescript AssemblyScript class SurveillanceAgent extends Agent { private monitoredSectors: string[] = []; @@ -512,7 +619,7 @@ class SurveillanceAgent extends Agent { return `Data processed automatically.\nTracking ${this.sightingsTracked} sightings. Matrix integrity: COMPROMISED`; } - + private getOperationalStatus(): string { return `Surveillance Agent Status: - Operational: Active @@ -533,7 +640,7 @@ class SurveillanceAgent extends Agent { // this.monitoredSectors = state.monitoredSectors; // this.sightingsTracked = state.sightingsTracked; // this.recentActivities = state.recentActivities; - // this.lastSweepTime = state.lastSweepTime; + // this.lastSweepTime = state.lastSweepTime; } } @@ -551,8 +658,7 @@ export function getSurveillanceStatus(agentId: string): string { } return result; } -```` - +``` Now let's enhance our original import function to automatically trigger @@ -567,19 +673,26 @@ func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, } s.AiAnalysis = &analysis -data, err := json.Marshal(s) if err != nil { return nil, err } - -mutation := dgraph.NewMutation().WithSetJson(string(data)) if \_, err := -dgraph.ExecuteMutations("dgraph", mutation); err != nil { return nil, err } + data, err := json.Marshal(s) + if err != nil { + return nil, err + } -if surveillanceAgentId != nil { if err := -agents.SendMessageAsync(\*surveillanceAgentId, "continuous_surveillance"); err -!= nil { return nil, err } } + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } -res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) return &res, -nil } + if surveillanceAgentId != nil { + if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { + return nil, err + } + } -```` + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil +} +``` ```typescript AssemblyScript export function importAgentSighting(s: AgentSighting, surveilanceAgentId: string | null = null): string { const analysis = analyzeAgentWithAI(s.behavior); @@ -594,8 +707,7 @@ export function importAgentSighting(s: AgentSighting, surveilanceAgentId: string return "Agent sighting processed " + s.sighting_id; } -```` - +``` Deploy your surveillance agent: From d5a4d8634c216e8dbbbc254bc238afae1c4f2f45 Mon Sep 17 00:00:00 2001 From: Ryan Fox-Tyler <60440289+ryanfoxtyler@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:07:44 -0700 Subject: [PATCH 12/15] fix spacing --- modus/functions.mdx | 86 ++++++++++------ modus/knowledge-graphs.mdx | 199 +++++++++++++++++++++---------------- 2 files changed, 165 insertions(+), 120 deletions(-) diff --git a/modus/functions.mdx b/modus/functions.mdx index bd55ba2b..e56c1ec3 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -44,6 +44,7 @@ GraphQL API. Your functions become either **queries** (for data retrieval) or Most functions become GraphQL queries—perfect for fetching and processing data: + ```go Go // This function becomes a GraphQL query func GatherThreatIntelligence(source string) (*ThreatReport, error) { @@ -51,6 +52,7 @@ func GatherThreatIntelligence(source string) (*ThreatReport, error) { return fetchThreatData(source) } ``` + ```ts AssemblyScript // This function becomes a GraphQL query export function gatherThreatIntelligence(source: string): ThreatReport { @@ -58,6 +60,7 @@ export function gatherThreatIntelligence(source: string): ThreatReport { return fetchThreatData(source) } ``` + Your functions are now accessible via GraphQL: @@ -92,6 +95,7 @@ Functions that modify data automatically become GraphQL mutations. Modus detects these by their operation prefixes: + ```go Go // This becomes a GraphQL mutation func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) { @@ -99,6 +103,7 @@ func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) { return deploySecurityAlert(data) } ``` + ```ts AssemblyScript // This becomes a GraphQL mutation export function createSecurityAlert(data: AlertInput): SecurityAlert { @@ -106,6 +111,7 @@ export function createSecurityAlert(data: AlertInput): SecurityAlert { return deploySecurityAlert(data) } ``` + Now you can execute data modifications: @@ -149,7 +155,8 @@ Here's a complete example that demonstrates how functions integrate external APIs with AI models for intelligent data processing: - ```go Go + +```go Go package main import ( @@ -264,83 +271,98 @@ func analyzeTacticalConditions(city string, temp float64, conditions string) (st return strings.TrimSpace(output.Choices[0].Message.Content), nil } ``` + ```ts AssemblyScript -import { http, models } from "@hypermode/modus-sdk-as"; -import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; +import { http, models } from "@hypermode/modus-sdk-as" +import { + OpenAIChatModel, + SystemMessage, + UserMessage, +} from "@hypermode/modus-sdk-as/models/openai/chat" @json class WeatherIntel { - city!: string; - temperature!: f64; - conditions!: string; - analysis!: string; + city!: string + temperature!: f64 + conditions!: string + analysis!: string } @json class WeatherData { - name!: string; - main!: MainWeatherData; - weather!: WeatherDescription[]; + name!: string + main!: MainWeatherData + weather!: WeatherDescription[] } @json class MainWeatherData { - temp!: f64; + temp!: f64 } @json class WeatherDescription { - description!: string; + description!: string } -const modelName = "text-generator"; +const modelName = "text-generator" export function gatherWeatherIntelligence(city: string): WeatherIntel { - city = encodeURIComponent(city); - const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric`; - const response = http.fetch(url); + city = encodeURIComponent(city) + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric` + const response = http.fetch(url) if (!response.ok) - throw new Error("Weather data retrieval failed: " + response.status.toString() + " " + response.statusText); + throw new Error( + "Weather data retrieval failed: " + + response.status.toString() + + " " + + response.statusText, + ) - const weatherData = response.json(); + const weatherData = response.json() let conditions = "unknown" - if (weatherData.weather.length) conditions = weatherData.weather[0].description; + if (weatherData.weather.length) + conditions = weatherData.weather[0].description const analysis = analyzeTacticalConditions( weatherData.name, weatherData.main.temp, - conditions - ); + conditions, + ) return { city: weatherData.name, temperature: weatherData.main.temp, conditions, - analysis - }; + analysis, + } } -function analyzeTacticalConditions(city: string, temperature: f64, conditions: string): string { - const model = models.getModel(modelName); +function analyzeTacticalConditions( + city: string, + temperature: f64, + conditions: string, +): string { + const model = models.getModel(modelName) const 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.`; + outdoor activities, visibility, and operational considerations in 1-2 sentences.` - const content = `Location: ${city}, Temperatire: ${temperature}, Conditions: ${conditions}`; + const content = `Location: ${city}, Temperatire: ${temperature}, Conditions: ${conditions}` const input = model.createInput([ new SystemMessage(prompt), - new UserMessage(content) - ]); - input.temperature = 0.7; + new UserMessage(content), + ]) + input.temperature = 0.7 - const output = model.invoke(input); + const output = model.invoke(input) - return output.choices[0].message.content.trim(); + return output.choices[0].message.content.trim() } ``` diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 269bf248..b7ac934d 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -84,6 +84,7 @@ When new Agent activity is detected in the Matrix, you need to process it quickly. This is perfect for a stateless function: + ```go Go package main @@ -162,28 +163,33 @@ func analyzeAgentWithAI(behavior string) (string, error) { return strings.TrimSpace(out.Choices[0].Message.Content), nil } ``` + ```typescript AssemblyScript -import { Agent, agents, dgraph, models } from "@hypermode/modus-sdk-as"; -import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; -import { JSON } from "json-as"; +import { Agent, agents, dgraph, models } from "@hypermode/modus-sdk-as" +import { + OpenAIChatModel, + SystemMessage, + UserMessage, +} from "@hypermode/modus-sdk-as/models/openai/chat" +import { JSON } from "json-as" @json class AgentSighting { - sighting_id!: string; - agent_name!: string; - location!: string; - behavior!: string; - timestamp!: string; + sighting_id!: string + agent_name!: string + location!: string + behavior!: string + timestamp!: string @omitnull() - ai_analysis: string | null = null; + ai_analysis: string | null = null } @json class ThreatAnalysisResponse { - sightings_count!: i32; - active_agents!: string[]; - threat_assessment!: string; - reccommendations!: string[]; + sightings_count!: i32 + active_agents!: string[] + threat_assessment!: string + reccommendations!: string[] } @json @@ -192,30 +198,32 @@ class SightingsData { } export function importAgentSighting(s: AgentSighting): string { - const analysis = analyzeAgentWithAI(s.behavior); - s.ai_analysis = analysis; + const analysis = analyzeAgentWithAI(s.behavior) + s.ai_analysis = analysis - const mutation = new dgraph.Mutation(JSON.stringify(s)); - dgraph.executeMutations("dgraph", mutation); + const mutation = new dgraph.Mutation(JSON.stringify(s)) + dgraph.executeMutations("dgraph", mutation) - return "Agent sighting processed " + s.sighting_id; + return "Agent sighting processed " + s.sighting_id } function analyzeAgentWithAI(behavior: string): string { - const model = models.getModel("text-generator"); + const model = models.getModel("text-generator") - const prompt = "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences."; + const prompt = + "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." const input = model.createInput([ new SystemMessage(prompt), - new UserMessage(behavior) - ]); - input.temperature = 0.3; + new UserMessage(behavior), + ]) + input.temperature = 0.3 - const out = model.invoke(input); - return out.choices[0].message.content.trim(); + const out = model.invoke(input) + return out.choices[0].message.content.trim() } ``` + Now let's deploy this data import function and test it: @@ -253,6 +261,7 @@ Now that we've got the Agent sighting data in our knowledge graph, let's analyze the broader threat landscape: + ```go Go func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { query := dgraph.NewQuery(` @@ -351,53 +360,55 @@ func generateRecommendations(count int) []string { } } ``` + ```typescript AssemblyScript export function analyzeAgentPatterns(since: string): ThreatAnalysisResponse { const query = new dgraph.Query(` - query analyzeAgents($since: string) { - sightings(func: ge(timestamp, $since)) { - sighting_id - agent_name - location - behavior - threat_level - timestamp - ai_analysis - } - } - `).withVariable("since", since); + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } + } + `).withVariable("since", since) - const resp = dgraph.executeQuery("dgraph", query); + const resp = dgraph.executeQuery("dgraph", query) - const data = JSON.parse(resp.Json); + const data = JSON.parse(resp.Json) - const assessment = generateThreatAssessment(data.sightings); + const assessment = generateThreatAssessment(data.sightings) return { sightings_count: data.sightings.length, active_agents: extractActiveAgents(data.sightings), threat_assessment: assessment, - reccommendations: generateRecommendations(data.sightings.length) - }; + reccommendations: generateRecommendations(data.sightings.length), + } } function generateThreatAssessment(sightings: AgentSighting[]): string { - const model = models.getModel("text-generator"); + const model = models.getModel("text-generator") - const prompt = "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + const prompt = + "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." const input = model.createInput([ new SystemMessage(prompt), - new UserMessage(JSON.stringify(sightings)) - ]); - input.temperature = 0.4; + new UserMessage(JSON.stringify(sightings)), + ]) + input.temperature = 0.4 - const out = model.invoke(input); - return out.choices[0].message.content.trim(); + const out = model.invoke(input) + return out.choices[0].message.content.trim() } function extractActiveAgents(sightings: AgentSighting[]): string[] { - return sightings.map(s => s.agent_name); + return sightings.map((s) => s.agent_name) } function generateRecommendations(count: i32): string[] { @@ -406,19 +417,18 @@ function generateRecommendations(count: i32): string[] { "Implement additional security measures.", "Enhance threat detection capabilities.", "Implement enhanced access control.", - ]; + ] } else if (count > 2) { return [ "Enhance threat detection capabilities.", "Implement enhanced access control.", ] } else { - return [ - "Implement additional security measures." - ] + return ["Implement additional security measures."] } } ``` + Let's query our surveillance data: @@ -462,6 +472,7 @@ data arrives. We'll deploy persistent surveillance agents and upgrade our import function to trigger them: + ```go Go import ( "time" @@ -569,29 +580,34 @@ func GetSurveillanceStatus(agentId string) (string, error) { return *result, nil } ``` + ```typescript AssemblyScript class SurveillanceAgent extends Agent { - private monitoredSectors: string[] = []; - private sightingsTracked: i32 = 0; - private recentActivities: string[] = []; - private lastSweepTime: Date = new Date(0); + private monitoredSectors: string[] = [] + private sightingsTracked: i32 = 0 + private recentActivities: string[] = [] + private lastSweepTime: Date = new Date(0) get name(): string { - return "SurveillanceAgent"; + return "SurveillanceAgent" } onInitialize(): void { - this.monitoredSectors = ["Downtown Loop", "Megacity Financial", "Industrial District"]; - this.lastSweepTime = new Date(Date.now()); + this.monitoredSectors = [ + "Downtown Loop", + "Megacity Financial", + "Industrial District", + ] + this.lastSweepTime = new Date(Date.now()) } onReceiveMessage(msgName: string, data: string | null): string { if (msgName === "continuous_surveillance") { - return this.processNewIntelligence(); + return this.processNewIntelligence() } else if (msgName === "get_status") { - return this.getOperationalStatus(); + return this.getOperationalStatus() } - throw new Error("Unrecognized directive: " + msgName); + throw new Error("Unrecognized directive: " + msgName) } private processNewIntelligence(): string { @@ -603,30 +619,30 @@ class SurveillanceAgent extends Agent { location } } - `).withVariable("since", this.lastSweepTime.toISOString()); + `).withVariable("since", this.lastSweepTime.toISOString()) - dgraph.executeQuery("dgraph", query); + dgraph.executeQuery("dgraph", query) - this.lastSweepTime = new Date(Date.now()); - this.sightingsTracked++; + this.lastSweepTime = new Date(Date.now()) + this.sightingsTracked++ - const activity = "Auto surveillance at " + this.lastSweepTime.toTimeString(); - this.recentActivities.push(activity); + const activity = "Auto surveillance at " + this.lastSweepTime.toTimeString() + this.recentActivities.push(activity) if (this.recentActivities.length > 3) { - this.recentActivities.shift(); + this.recentActivities.shift() } - return `Data processed automatically.\nTracking ${this.sightingsTracked} sightings. Matrix integrity: COMPROMISED`; + return `Data processed automatically.\nTracking ${this.sightingsTracked} sightings. Matrix integrity: COMPROMISED` } - + private getOperationalStatus(): string { return `Surveillance Agent Status: - Operational: Active - Monitoring ${this.monitoredSectors.length.toString()} sectors: ${this.monitoredSectors.join(", ")} - Last sweep: ${this.lastSweepTime.toISOString().replace("T", " ").slice(0, 19)} - Tracking ${this.sightingsTracked.toString()} ongoing sightings -- Recent activities: ${this.recentActivities.join(", ")}`; +- Recent activities: ${this.recentActivities.join(", ")}` } getState(): string { @@ -640,31 +656,33 @@ class SurveillanceAgent extends Agent { // this.monitoredSectors = state.monitoredSectors; // this.sightingsTracked = state.sightingsTracked; // this.recentActivities = state.recentActivities; - // this.lastSweepTime = state.lastSweepTime; + // this.lastSweepTime = state.lastSweepTime; } } -agents.register(); +agents.register() export function deploySurveillanceAgent(): string { - const agentInfo = agents.start("SurveillanceAgent"); - return `${agentInfo.name} - ${agentInfo.id}`; + const agentInfo = agents.start("SurveillanceAgent") + return `${agentInfo.name} - ${agentInfo.id}` } export function getSurveillanceStatus(agentId: string): string { - const result = agents.sendMessage(agentId, "get_status"); + const result = agents.sendMessage(agentId, "get_status") if (result == null) { - throw new Error("No response from agent"); + throw new Error("No response from agent") } - return result; + return result } ``` + Now let's enhance our original import function to automatically trigger surveillance: + ```go Go func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, error) { analysis, err := analyzeAgentWithAI(s.Behavior) @@ -693,21 +711,26 @@ func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, return &res, nil } ``` + ```typescript AssemblyScript -export function importAgentSighting(s: AgentSighting, surveilanceAgentId: string | null = null): string { - const analysis = analyzeAgentWithAI(s.behavior); - s.ai_analysis = analysis; +export function importAgentSighting( + s: AgentSighting, + surveilanceAgentId: string | null = null, +): string { + const analysis = analyzeAgentWithAI(s.behavior) + s.ai_analysis = analysis - const mutation = new dgraph.Mutation(JSON.stringify(s)); - dgraph.executeMutations("dgraph", mutation); + const mutation = new dgraph.Mutation(JSON.stringify(s)) + dgraph.executeMutations("dgraph", mutation) if (surveilanceAgentId) { - agents.sendMessageAsync(surveilanceAgentId, "continuous_surveillance"); + agents.sendMessageAsync(surveilanceAgentId, "continuous_surveillance") } - return "Agent sighting processed " + s.sighting_id; + return "Agent sighting processed " + s.sighting_id } ``` + Deploy your surveillance agent: From 2b64b4eac48eb900fb7470fb17eb7db5617c6e00 Mon Sep 17 00:00:00 2001 From: Jairus Tanaka Date: Thu, 10 Jul 2025 09:00:38 -0700 Subject: [PATCH 13/15] fix: must alias author (a) and quote (q) --- modus/first-modus-agent.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modus/first-modus-agent.mdx b/modus/first-modus-agent.mdx index f2f884db..126a7b07 100644 --- a/modus/first-modus-agent.mdx +++ b/modus/first-modus-agent.mdx @@ -121,8 +121,8 @@ AssemblyScript if you prefer. For AssemblyScript usage, refer to the ) type IntelReport struct { - Quote string `json:"quote"` - Author string `json:"author"` + Quote string `json:"q"` + Author string `json:"a"` Analysis string `json:"analysis,omitempty"` } From ff9c11470d0f69f93be74b1db8787e1796aa158a Mon Sep 17 00:00:00 2001 From: Jairus Date: Mon, 14 Jul 2025 14:39:48 -0700 Subject: [PATCH 14/15] fix: finish go agent docs --- modus/agents.mdx | 570 +++++++++++++++++++++-------------------------- 1 file changed, 256 insertions(+), 314 deletions(-) diff --git a/modus/agents.mdx b/modus/agents.mdx index d9597df2..564c257b 100644 --- a/modus/agents.mdx +++ b/modus/agents.mdx @@ -39,34 +39,72 @@ Every agent starts with the essential framework: package main import ( - "fmt" - "strings" - "time" - "github.com/hypermodeinc/modus/sdk/go/pkg/agents" - "github.com/hypermodeinc/modus/sdk/go/pkg/models" - "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" + "encoding/json" + "errors" + "fmt" + "math" + "strings" + "time" + + "github.com/hypermodeinc/modus/sdk/go/pkg/agents" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" ) type IntelligenceAgent struct { - agents.AgentBase - - // The rest of the fields make up the agent's state and can be customized per agent - intelligenceReports []string // Matrix surveillance data - threatLevel float64 // Current threat assessment - lastContact time.Time - currentMission *MissionPhase // Track long-running operations - missionLog []string // Operational progress log + agents.AgentBase + intelligenceReports []string + threatLevel float64 + lastContact time.Time + currentMission *MissionPhase + missionLog []string } type MissionPhase struct { - Name string - StartTime time.Time - Duration time.Duration - Complete bool + Name string + StartTime time.Time + Duration time.Duration + Complete bool +} + +type MissionStatus struct { + Phase string `json:"phase"` + Progress float64 `json:"progress"` + CurrentTask string `json:"current_task"` + EstimatedTimeRemaining int `json:"estimated_time_remaining"` + IsComplete bool `json:"is_complete"` +} + +type ThreatDetected struct { + ThreatLevel string `json:"threatLevel"` + Confidence float64 `json:"confidence"` + Analysis string `json:"analysis"` +} + +type MissionStarted struct { + MissionName string `json:"missionName"` + Priority string `json:"priority"` + ActivityData int `json:"activityData"` +} + +type SurveillanceProgress struct { + Phase string `json:"phase"` + Progress float64 `json:"progress"` + ReportsProcessed int `json:"reportsProcessed"` + TotalReports int `json:"totalReports"` +} + +type AIAnalysisStarted struct { + ModelName string `json:"modelName"` + ContextSize int `json:"contextSize"` + ReportCount int `json:"reportCount"` } -func (a *IntelligenceAgent) Name() string { - return "IntelligenceAgent" +type MissionCompleted struct { + MissionName string `json:"missionName"` + Confidence float64 `json:"confidence"` + ReportsAnalyzed int `json:"reportsAnalyzed"` + Status string `json:"status"` } ``` @@ -81,20 +119,16 @@ Agents are created and managed through regular Modus functions that become part of your GraphQL API. These functions handle agent lifecycle operations: ```go -// Register your agent type during initialization func init() { - agents.Register(&IntelligenceAgent{}) + agents.Register(&IntelligenceAgent{}) } -// Create a new agent instance - this becomes a GraphQL mutation func DeployAgent() (string, error) { - agentInfo, err := agents.Start("IntelligenceAgent") - if err != nil { - return "", err - } - - // Return the agent ID - clients must store this to communicate with the agent - return agentInfo.Id, nil + info, err := agents.Start("IntelligenceAgent") + if err != nil { + return "", err + } + return info.Id, nil } ``` @@ -111,7 +145,7 @@ Response: ```json { "data": { - "deployAgent": "agent_neo_001" + "deployAgent": "d1qn141d6u7qu64mesjg" } } ``` @@ -135,30 +169,27 @@ Once created, you communicate with agents using their unique ID. Create functions that send messages to specific agent instances: ```go -func ImportActivity(agentId string, activityData string) (string, error) { - result, err := agents.SendMessage( - agentId, - "matrix_surveillance", - agents.WithData(activityData), - ) - if err != nil { - return "", err - } - if result == nil { - return "", fmt.Errorf("no response from agent") - } - return *result, nil + +func ImportActivity(agentId, activityData string) (string, error) { + res, err := agents.SendMessage(agentId, "matrix_surveillance", agents.WithData(activityData)) + if err != nil { + return "", err + } + if res == nil { + return "", errors.New("no response from agent") + } + return *res, nil } func GetThreatStatus(agentId string) (string, error) { - result, err := agents.SendMessage(agentId, "threat_assessment") - if err != nil { - return "", err - } - if result == nil { - return "", fmt.Errorf("no response from agent") - } - return *result, nil + res, err := agents.SendMessage(agentId, "threat_assessment") + if err != nil { + return "", err + } + if res == nil { + return "", errors.New("no response from agent") + } + return *res, nil } ``` @@ -168,7 +199,7 @@ ID: ```graphql mutation { importActivity( - agentId: "agent_neo_001" + agentId: "d1qn141d6u7qu64mesjg" activityData: "Anomalous Agent Smith replication detected in Sector 7" ) } @@ -189,7 +220,7 @@ Response: ```graphql query { - getThreatStatus(agentId: "agent_neo_001") + threatStatus(agentId: "d1qn141d6u7qu64mesjg") } ``` @@ -198,7 +229,7 @@ Response: ```json { "data": { - "getThreatStatus": "Current threat assessment: + "threatStatus": "Current threat assessment: 3 intelligence reports analyzed. Threat level: 0.89. Agent operational in the Matrix." @@ -215,24 +246,19 @@ maintaining persistent memory of every interaction. Agents process requests through their message handling system: ```go -func (a *IntelligenceAgent) OnReceiveMessage( - msgName string, - data string, -) (*string, error) { - switch msgName { - case "matrix_surveillance": - return a.analyzeMatrixActivity(data) - case "background_reconnaissance": - return a.performBackgroundRecon(data) - case "threat_assessment": - return a.getThreatAssessment() - case "get_status": - return a.getOperationalStatus() - case "intelligence_history": - return a.getIntelligenceHistory() - default: - return nil, fmt.Errorf("unrecognized directive: %s", msgName) - } +func (a *IntelligenceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { + switch msgName { + case "matrix_surveillance": + return a.analyzeMatrixActivity(data) + case "background_reconnaissance": + return a.performBackgroundRecon(data) + case "threat_assessment": + return a.getThreatAssessment() + case "get_status": + return a.getOperationalStatus() + default: + return nil, fmt.Errorf("unrecognized directive: %s", msgName) + } } ``` @@ -245,64 +271,36 @@ Here's how agents handle operations while maintaining persistent state and using AI models for analysis: ```go -func (a *IntelligenceAgent) analyzeMatrixActivity(data string) (*string, error) { - // Store new intelligence in persistent memory - a.intelligenceReports = append(a.intelligenceReports, *data) - a.lastContact = time.Now() - - // Build context from all accumulated intelligence - accumulatedReports := strings.Join(a.intelligenceReports, "\n") - - // AI analysis using complete operational history - model, err := models.GetModel[openai.ChatModel]("analyst-model") - if err != nil { - return nil, err - } - - systemPrompt := `You are a resistance operative in the Matrix. - Analyze patterns from accumulated surveillance reports - and provide threat assessment for anomalous Agent behavior.` - - userPrompt := fmt.Sprintf(`All Matrix Intelligence: - %s +func (a *IntelligenceAgent) analyzeActivity(data *string) (*string, error) { + a.IntelReports = append(a.IntelReports, *data) + a.LastContact = time.Now() - Provide threat assessment:`, - accumulatedReports) - - input, err := model.CreateInput( - openai.NewSystemMessage(systemPrompt), - openai.NewUserMessage(userPrompt), - ) - if err != nil { - return nil, err - } - - output, err := model.Invoke(input) - if err != nil { - return nil, err - } - analysis := output.Choices[0].Message.Content + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return nil, err + } - // Update threat level based on data volume and AI analysis - a.threatLevel = float64(len(a.intelligenceReports)) / 10.0 - if a.threatLevel > 1.0 { - a.threatLevel = 1.0 - } + input, err := model.CreateInput( + openai.NewSystemMessage("You are a resistance operative in the Matrix. Analyze patterns from accumulated surveillance reports and provide threat assessment. Respond in no more than 3 concise sentences."), + openai.NewUserMessage(fmt.Sprintf("All Matrix Intelligence:\n%s\n\nProvide threat assessment:", strings.Join(a.IntelReports, "\n"))), + ) + if err != nil { + return nil, err + } - // Boost threat level for critical AI analysis - if strings.Contains(strings.ToLower(analysis), "critical") || - strings.Contains(strings.ToLower(analysis), "agent smith") { - a.threatLevel = math.Min(a.threatLevel + 0.2, 1.0) - } + output, err := model.Invoke(input) + if err != nil { + return nil, err + } + analysis := output.Choices[0].Message.Content - result := fmt.Sprintf(`Matrix surveillance complete: - %s + a.ThreatLevel = math.Min(1.0, float64(len(a.IntelReports))/10.0) + if s := strings.ToLower(analysis); strings.Contains(s, "critical") || strings.Contains(s, "agent smith") { + a.ThreatLevel = math.Min(a.ThreatLevel+0.2, 1.0) + } - (Threat level: %.2f based on %d intelligence reports)`, - analysis, - a.threatLevel, - len(a.intelligenceReports)) - return &result, nil + result := fmt.Sprintf("Matrix surveillance complete:\n%s\n\n(Threat level: %.2f based on %d intelligence reports)", analysis, a.ThreatLevel, len(a.IntelReports)) + return &result, nil } ``` @@ -335,28 +333,34 @@ system: ```go func (a *IntelligenceAgent) GetState() *string { - reportsData := strings.Join(a.intelligenceReports, "|") - state := fmt.Sprintf("%.2f|%s|%d", - a.threatLevel, - reportsData, - a.lastContact.Unix()) - return &state + state := AgentState{ + ThreatLevel: a.threatLevel, + IntelligenceReports: a.intelligenceReports, + LastContactUnix: a.lastContact.Unix(), + CurrentMission: a.currentMission, + MissionLog: a.missionLog, + } + bytes, err := json.Marshal(state) + if err != nil { + return nil + } + result := string(bytes) + return &result } -func (a *IntelligenceAgent) SetState(data string) { - if data == nil { - return - } - - parts := strings.Split(*data, "|") - if len(parts) >= 3 { - a.threatLevel, _ = strconv.ParseFloat(parts[0], 64) - if parts[1] != "" { - a.intelligenceReports = strings.Split(parts[1], "|") - } - timestamp, _ := strconv.ParseInt(parts[2], 10, 64) - a.lastContact = time.Unix(timestamp, 0) - } +func (a *IntelligenceAgent) SetState(data *string) { + if data == nil { + return + } + state := AgentState{} + if err := json.Unmarshal([]byte(*data), &state); err != nil { + return + } + a.threatLevel = state.ThreatLevel + a.intelligenceReports = state.IntelligenceReports + a.lastContact = time.Unix(state.LastContactUnix, 0) + a.currentMission = state.CurrentMission + a.missionLog = state.MissionLog } ``` @@ -366,36 +370,26 @@ Agents have built-in lifecycle management protocols: ```go func (a *IntelligenceAgent) OnInitialize() error { - // Called when agent is first created - a.lastContact = time.Now() - a.threatLevel = 0.0 - - fmt.Printf(`Resistance Agent %s awakened - and ready for Matrix surveillance`, a.Id()) - return nil + a.lastContact = time.Now(); + a.threatLevel = 0; + fmt.Printf("Agent %s ready\n", a.Id()); + return nil } func (a *IntelligenceAgent) OnResume() error { - // Called when agent reconnects with complete state intact - fmt.Printf(`Agent back online in the Matrix. - %d intelligence reports processed. - Threat level: %.2f`, - len(a.intelligenceReports), - a.threatLevel) - return nil + fmt.Printf("Agent resumed. Reports: %d, Threat Level: %.2f\n", len(a.intelligenceReports), a.threatLevel); + return nil } func (a *IntelligenceAgent) OnSuspend() error { - // Called before agent goes offline - return nil + return nil } func (a *IntelligenceAgent) OnTerminate() error { - // Called before final shutdown - fmt.Printf(`Agent %s extracted from Matrix. - Intelligence archive preserved.`, a.Id()) - return nil + fmt.Printf("Agent %s terminated. Archive saved.\n", a.Id()); + return nil } + ``` ## Asynchronous operations @@ -404,19 +398,12 @@ For fire-and-forget operations where you don't need to wait for a response, agents support asynchronous messaging: ```go -func InitiateBackgroundRecon(agentId string, data string) error { - // Send message asynchronously - agent processes in background - err := agents.SendMessageAsync( - agentId, - "background_reconnaissance", - agents.WithData(data), - ) - if err != nil { - return err - } - - // Operation initiated - agent continues processing independently - return nil +func InitiateBackgroundRecon(agentId, data string) error { + return agents.SendMessageAsync( + agentId, + "background_reconnaissance", + agents.WithData(data) + ) } ``` @@ -440,7 +427,7 @@ Monitor your agent's real-time activities using the unified event subscription: ```graphql subscription { - agentEvent(agentId: "agent_neo_001") { + agentEvent(agentId: "d1qn141d6u7qu64mesjg") { name data timestamp @@ -512,110 +499,72 @@ type ThreatDetected struct { Confidence float64 `json:"confidence"` Analysis string `json:"analysis"` } - -func (e ThreatDetected) EventName() string { - return "threat_detected" -} +func (ThreatDetected) EventName() string { return "threat_detected" } // Other event types can be defined similarly... -func (a *IntelligenceAgent) analyzeMatrixActivity( - data string, -) (*string, error) { - // Emit mission start event - err := a.PublishEvent(MissionStarted{ - MissionName: "Matrix Surveillance Analysis", - Priority: "HIGH", - ActivityData: len(*data), - }) - if err != nil { - return nil, err - } - - // Store new intelligence in persistent memory - a.intelligenceReports = append(a.intelligenceReports, *data) - a.lastContact = time.Now() - - // Emit progress update - a.PublishEvent(SurveillanceProgress{ - ReportsProcessed: len(a.intelligenceReports), - Phase: "Processing Matrix surveillance data", - Progress: 0.3, - }) - - // Build context from all accumulated intelligence - accumulatedReports := strings.Join(a.intelligenceReports, "\n") - - // AI analysis using complete operational history - model, err := models.GetModel[openai.ChatModel]("analyst-model") - if err != nil { - return nil, err - } - - systemPrompt := `You are a resistance operative in the Matrix. - Analyze patterns from accumulated surveillance reports - and provide threat assessment for anomalous Agent behavior.` - - userPrompt := fmt.Sprintf(`All Matrix Intelligence: - %s - - Provide threat assessment:`, - accumulatedReports) - - input, err := model.CreateInput( - openai.NewSystemMessage(systemPrompt), - openai.NewUserMessage(userPrompt), - ) - if err != nil { - return nil, err - } +func (a *IntelligenceAgent) analyzeMatrixActivity(data *string) (*string, error) { + a.PublishEvent(MissionStarted{ + MissionName: "Matrix Surveillance Analysis", + Priority: "HIGH", + ActivityData: len(*data), + }) + + a.intelligenceReports = append(a.intelligenceReports, *data) + a.lastContact = time.Now() + + a.PublishEvent(SurveillanceProgress{ + Phase: "Processing Matrix surveillance data", + Progress: 0.3, + ReportsProcessed: len(a.intelligenceReports), + TotalReports: len(a.intelligenceReports), + }) + + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return nil, err + } - // Emit AI processing event - a.PublishEvent(AIAnalysisStarted{ - ModelName: "analyst-model", - ContextSize: len(accumulatedReports), - ReportCount: len(a.intelligenceReports), - }) + a.PublishEvent(AIAnalysisStarted{ + ModelName: "text-generator", + ContextSize: len(strings.Join(a.intelligenceReports, "\n")), + ReportCount: len(a.intelligenceReports), + }) - output, err := model.Invoke(input) - if err != nil { - return nil, err - } - analysis := output.Choices[0].Message.Content + input, err := model.CreateInput( + openai.NewSystemMessage("You are a resistance operative in the Matrix. Analyze patterns from accumulated surveillance reports and provide threat assessment."), + openai.NewUserMessage(fmt.Sprintf("All Matrix Intelligence:\n%s\n\nProvide threat assessment:", strings.Join(a.intelligenceReports, "\n"))), + ) + if err != nil { + return nil, err + } - // Update threat level based on data volume and AI analysis - a.threatLevel = float64(len(a.intelligenceReports)) / 10.0 - if a.threatLevel > 1.0 { - a.threatLevel = 1.0 - } + output, err := model.Invoke(input) + if err != nil { + return nil, err + } - // Check for Agent threats and emit alerts - if strings.Contains(strings.ToLower(analysis), "critical") || - strings.Contains(strings.ToLower(analysis), "agent smith") { - a.threatLevel = math.Min(a.threatLevel + 0.2, 1.0) - a.PublishEvent(ThreatDetected{ - ThreatLevel: "HIGH", - Confidence: a.threatLevel, - Analysis: analysis, - }) - } + analysis := output.Choices[0].Message.Content + a.threatLevel = math.Min(1.0, float64(len(a.intelligenceReports))/10.0) - // Emit mission completion - a.PublishEvent(MissionCompleted{ - MissionName: "Matrix Surveillance Analysis", - Confidence: a.threatLevel, - ReportsAnalyzed: len(a.intelligenceReports), - Status: "SUCCESS", + if strings.Contains(strings.ToLower(analysis), "critical") || strings.Contains(strings.ToLower(analysis), "agent smith") { + a.threatLevel = math.Min(a.threatLevel+0.2, 1.0) + a.PublishEvent(ThreatDetected{ + ThreatLevel: "HIGH", + Confidence: a.threatLevel, + Analysis: analysis, }) + } - result := fmt.Sprintf(`Matrix surveillance complete: - %s + a.PublishEvent(MissionCompleted{ + MissionName: "Matrix Surveillance Analysis", + Confidence: a.threatLevel, + ReportsAnalyzed: len(a.intelligenceReports), + Status: "SUCCESS", + }) - (Threat level: %.2f based on %d intelligence reports)`, - analysis, - a.threatLevel, - len(a.intelligenceReports)) - return &result, nil + result := fmt.Sprintf("Matrix surveillance complete:\n%s\n\n(Threat level: %.2f based on %d reports)", analysis, a.threatLevel, len(a.intelligenceReports)) + return &result, nil } ``` @@ -655,7 +604,7 @@ Example with curl: curl -N -H "accept: text/event-stream" \ -H "content-type: application/json" \ -X POST http://localhost:8080/graphql \ - -d '{"query":"subscription { agentEvent(agentId: \"agent_neo_001\") { name data timestamp } }"}' + -d '{"query":"subscription { agentEvent(agentId: \"d1qn141d6u7qu64mesjg\") { name data timestamp } }"}' ``` ## Monitoring ongoing operations @@ -664,20 +613,15 @@ You can also poll agent status directly through dedicated functions: ```go func CheckMissionProgress(agentId string) (*MissionStatus, error) { - result, err := agents.SendMessage(agentId, "get_status") - if err != nil { - return nil, err - } - if result == nil { - return nil, fmt.Errorf("no response from agent") - } - - var status MissionStatus - err = json.Unmarshal([]byte(*result), &status) - if err != nil { - return nil, err - } - return &status, nil + res, err := agents.SendMessage(agentId, "get_status") + if err != nil || res == nil { + return nil, err + } + var status MissionStatus + if err := json.Unmarshal([]byte(*res), &status); err != nil { + return nil, err + } + return &status, nil } type MissionStatus struct { @@ -694,34 +638,32 @@ earlier: ```go func (a *IntelligenceAgent) getOperationalStatus() (*string, error) { - var status MissionStatus - - if a.currentMission == nil { - status = MissionStatus{ - Phase: "Standby", - Progress: 1.0, - CurrentTask: "Awaiting mission directives in the Matrix", - IsComplete: true, - } - } else { - // Calculate progress based on mission log entries - progress := float64(len(a.missionLog)) / 4.0 // 4 phases expected - if progress > 1.0 { progress = 1.0 } - - status = MissionStatus{ - Phase: a.currentMission.Name, - Progress: progress, - CurrentTask: a.missionLog[len(a.missionLog)-1], // Latest entry - IsComplete: a.currentMission.Complete, - } - } + status := MissionStatus{ + Phase: "Standby", + Progress: 1.0, + CurrentTask: "Awaiting mission directives in the Matrix", + IsComplete: true, + } - statusJson, err := json.Marshal(status) - if err != nil { - return nil, err + if a.currentMission != nil && len(a.missionLog) > 0 { + progress := float64(len(a.missionLog)) / 4.0 + if progress > 1 { + progress = 1 + } + status = MissionStatus{ + Phase: a.currentMission.Name, + Progress: progress, + CurrentTask: a.missionLog[len(a.missionLog)-1], + IsComplete: a.currentMission.Complete, } - result := string(statusJson) - return &result, nil + } + + jsonData, err := json.Marshal(status) + if err != nil { + return nil, err + } + result := string(jsonData) + return &result, nil } ``` From b47668d2d23d242c8f9a6b0158a0ca0ba6d273b8 Mon Sep 17 00:00:00 2001 From: Jairus Date: Mon, 14 Jul 2025 16:07:55 -0700 Subject: [PATCH 15/15] docs: finish draft of agents --- modus/agents.mdx | 446 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 434 insertions(+), 12 deletions(-) diff --git a/modus/agents.mdx b/modus/agents.mdx index 564c257b..86b10d7b 100644 --- a/modus/agents.mdx +++ b/modus/agents.mdx @@ -35,6 +35,11 @@ Agents are perfect for: Every agent starts with the essential framework: + + + + `agents.go` + ```go package main @@ -59,7 +64,11 @@ type IntelligenceAgent struct { currentMission *MissionPhase missionLog []string } +``` + +`types.go` +```go Go Expandable type MissionPhase struct { Name string StartTime time.Time @@ -108,6 +117,126 @@ type MissionCompleted struct { } ``` + + + +`index.ts` + +```typescript +import { Agent } from "@hypermode/modus-sdk-as" +import { JSON } from "json-as" +import { MissionPhase } from "./types" + +@json +class IntelligenceAgent extends Agent { + private intelReports: string[] = [] + private threatLevel: f64 = 0 + private lastContact: u64 = 0 + private currentMission: MissionPhase | null = null + private missionLog: string[] = [] + + get name(): string { + return "IntelligenceAgent" + } +} +``` + +`types.ts` + +```typescript Expandable +import { AgentEvent } from "@hypermode/modus-sdk-as" + +@json +export class MissionPhase { + name: string = "" + startTime: u64 = 0 + duration: u64 = 0 + complete: bool = false +} + +@json +export class MissionStatus { + phase: string = "" + progress: f64 = 0 + currentTask: string = "" + estimatedTimeRemaining: i32 = 0 + isComplete: bool = false +} + +@json +export class ThreatDetected extends AgentEvent { + eventName: string = "threat_detected" + threatLevel: string = "" + confidence: f64 = 0 + analysis: string = "" + constructor(threatLevel: string, confidence: f64, analysis: string) { + super("threat_detected") + this.threatLevel = threatLevel + this.confidence = confidence + this.analysis = analysis + } +} + +@json +export class MissionStarted extends AgentEvent { + eventName: string = "mission_started" + missionName: string = "" + priority: string = "" + activityData: i32 = 0 + constructor(missionName: string, priority: string, activityData: i32) { + super("mission_started") + this.missionName = missionName + this.priority = priority + this.activityData = activityData + } +} + +@json +export class SurveillanceProgress extends AgentEvent { + eventName: string = "surveillance_progress" + phase: string = "" + progress: f64 = 0 + reportsProcessed: i32 = 0 + totalReports: i32 = 0 + constructor( + phase: string, + progress: f64, + reportsProcessed: i32, + totalReports: i32, + ) { + super("surveillance_progress") + this.phase = phase + this.progress = progress + this.reportsProcessed = reportsProcessed + this.totalReports = totalReports + } +} + +@json +export class MissionCompleted extends AgentEvent { + eventName: string = "mission_completed" + missionName: string = "" + confidence: f64 = 0 + reportsAnalyzed: i32 = 0 + status: string = "" + constructor( + missionName: string, + confidence: f64, + reportsAnalyzed: i32, + status: string, + ) { + super("mission_completed") + this.missionName = missionName + this.confidence = confidence + this.reportsAnalyzed = reportsAnalyzed + this.status = status + } +} +``` + + + + The agent embeds `agents.AgentBase`, which provides all the infrastructure for state management, secure communications, and persistence. Your app data—intelligence reports, threat assessments, contact logs—lives as fields in @@ -118,7 +247,9 @@ the struct, automatically preserved across all interactions. Agents are created and managed through regular Modus functions that become part of your GraphQL API. These functions handle agent lifecycle operations: -```go + + +```go Go func init() { agents.Register(&IntelligenceAgent{}) } @@ -132,6 +263,16 @@ func DeployAgent() (string, error) { } ``` +```typescript AssemblyScript +agents.register() + +export function deployAgent(): string { + return agents.start("IntelligenceAgent").id +} +``` + + + When you call this function through GraphQL, it returns a unique agent ID: ```graphql @@ -168,8 +309,9 @@ continues operating exactly where it left off. Once created, you communicate with agents using their unique ID. Create functions that send messages to specific agent instances: -```go + +```go Go func ImportActivity(agentId, activityData string) (string, error) { res, err := agents.SendMessage(agentId, "matrix_surveillance", agents.WithData(activityData)) if err != nil { @@ -193,6 +335,21 @@ func GetThreatStatus(agentId string) (string, error) { } ``` +```typescript AssemblyScript +export function importActivity( + agentId: string, + activityData: string, +): string | null { + return agents.sendMessage(agentId, "matrix_surveillance", activityData) +} + +export function getThreatStatus(agentId: string): string | null { + return agents.sendMessage(agentId, "threat_assessment") +} +``` + + + These functions become GraphQL operations that you can call with your agent's ID: @@ -245,7 +402,9 @@ maintaining persistent memory of every interaction. Agents process requests through their message handling system: -```go + + +```go Go func (a *IntelligenceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { switch msgName { case "matrix_surveillance": @@ -262,6 +421,31 @@ func (a *IntelligenceAgent) OnReceiveMessage(msgName string, data *string) (*str } ``` +```typescript AssemblyScript focus={3-20} +class IntelligenceAgent extends Agent { + // ... + onReceiveMessage(msgName: string, data: string | null): string | null { + switch (msgName) { + case "matrix_surveillance": + if (!data) return "No data provided" + return this.analyzeMatrixActivity(data) + case "background_reconnaissance": + if (!data) return "No data provided" + this.performBackgroundRecon(data) + return null + case "threat_assessment": + return this.getThreatAssessment() + case "get_status": + return this.getOperationalStatus() + default: + return `Unrecognized directive: ${msgName}` + } + } +} +``` + + + Each message type triggers specific operations, with all data automatically maintained in the agent's persistent memory. @@ -270,8 +454,10 @@ maintained in the agent's persistent memory. Here's how agents handle operations while maintaining persistent state and using AI models for analysis: -```go -func (a *IntelligenceAgent) analyzeActivity(data *string) (*string, error) { + + +```go Go +func (a *IntelligenceAgent) analyzeMatrixActivity(data *string) (*string, error) { a.IntelReports = append(a.IntelReports, *data) a.LastContact = time.Now() @@ -281,7 +467,11 @@ func (a *IntelligenceAgent) analyzeActivity(data *string) (*string, error) { } input, err := model.CreateInput( - openai.NewSystemMessage("You are a resistance operative in the Matrix. Analyze patterns from accumulated surveillance reports and provide threat assessment. Respond in no more than 3 concise sentences."), + openai.NewSystemMessage( + "You are a resistance operative in the Matrix. + Analyze patterns from accumulated surveillance reports and provide threat assessment. + Respond in no more than 3 concise sentences." + ), openai.NewUserMessage(fmt.Sprintf("All Matrix Intelligence:\n%s\n\nProvide threat assessment:", strings.Join(a.IntelReports, "\n"))), ) if err != nil { @@ -304,6 +494,67 @@ func (a *IntelligenceAgent) analyzeActivity(data *string) (*string, error) { } ``` +```typescript AssemblyScript focus={3-54} +class IntelligenceAgent extends Agent { + // ... + private analyzeMatrixActivity(data: string): string | null { + this.publishEvent( + new MissionStarted("Matrix Surveillance Analysis", "HIGH", data.length), + ) + + this.intelReports.push(data) + this.lastContact = Date.now() + + this.publishEvent( + new SurveillanceProgress( + "Processing Matrix surveillance data", + 0.3, + this.intelReports.length, + this.intelReports.length, + ), + ) + + const model = models.getModel("text-generator") + const prompt = ` + You are a resistance operative in the Matrix. + Analyze patterns from accumulated surveillance reports and provide threat assessment. + Respond in no more than 2 concise sentences.` + const content = + "All Matrix Intelligence:\n" + + this.intelReports.join("\n") + + "\n\nProvide threat assessment:" + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content), + ]) + const analysis = model.invoke(input).choices[0].message.content + + this.threatLevel = Math.min(1, this.intelReports.length / 10) + + if ( + analysis.toLowerCase().includes("critical") || + analysis.toLowerCase().includes("agent smith") + ) { + this.threatLevel = Math.min(this.threatLevel + 0.2, 1) + this.publishEvent(new ThreatDetected("HIGH", this.threatLevel, analysis)) + } + + this.publishEvent( + new MissionCompleted( + "Matrix Surveillance Analysis", + this.threatLevel, + this.intelReports.length, + "SUCCESS", + ), + ) + + return `Matrix surveillance complete:\n${analysis}\n\n(Threat level: ${this.threatLevel} based on ${this.intelReports.length} reports)` + } +} +``` + + + This demonstrates how agents maintain state across complex operations while using AI models with the full context of accumulated intelligence. @@ -331,7 +582,9 @@ sophisticated pattern recognition impossible with stateless functions. Agents automatically preserve their state through Modus's built-in persistence system: -```go + + +```go Go func (a *IntelligenceAgent) GetState() *string { state := AgentState{ ThreatLevel: a.threatLevel, @@ -364,11 +617,34 @@ func (a *IntelligenceAgent) SetState(data *string) { } ``` +```typescript AssemblyScript focus={3-15} +class IntelligenceAgent extends Agent { + // ... + getState(): string { + return JSON.stringify(this) + } + + setState(data: string | null): void { + if (!data) return + const agent = JSON.parse(data) + this.intelReports = agent.intelReports + this.threatLevel = agent.threatLevel + this.lastContact = agent.lastContact + this.currentMission = agent.currentMission + this.missionLog = agent.missionLog + } +} +``` + + + ## Agent lifecycle Agents have built-in lifecycle management protocols: -```go + + +```go Go func (a *IntelligenceAgent) OnInitialize() error { a.lastContact = time.Now(); a.threatLevel = 0; @@ -389,15 +665,41 @@ func (a *IntelligenceAgent) OnTerminate() error { fmt.Printf("Agent %s terminated. Archive saved.\n", a.Id()); return nil } +``` + +```typescript AssemblyScript focus={3-19} +class IntelligenceAgent extends Agent { + // ... + onInitialize(): void { + this.lastContact = Date.now() + this.threatLevel = 0 + console.log(`Agent ${this.id} ready`) + } + + onResume(): void { + console.log( + `Agent resumed. Reports: ${this.intelReports.length}, Threat Level: ${this.threatLevel}`, + ) + } + + onSuspend(): void {} + onTerminate(): void { + console.log(`Agent ${this.id} terminated. Archive saved`) + } +} ``` + + ## Asynchronous operations For fire-and-forget operations where you don't need to wait for a response, agents support asynchronous messaging: -```go + + +```go Go func InitiateBackgroundRecon(agentId, data string) error { return agents.SendMessageAsync( agentId, @@ -407,6 +709,14 @@ func InitiateBackgroundRecon(agentId, data string) error { } ``` +```typescript AssemblyScript +export function initiateBackgroundRecon(agentId: string, data: string): void { + agents.sendMessageAsync(agentId, "background_reconnaissance", data) +} +``` + + + This enables agents to handle long-running operations like: - Background Matrix monitoring with status updates @@ -492,7 +802,9 @@ Your agent streams various types of operational events: Agents can broadcast real-time operational intelligence by publishing events during their operations. Use the `PublishEvent` method to emit custom events: -```go + + +```go Go // Custom event types implement the AgentEvent interface type ThreatDetected struct { ThreatLevel string `json:"threatLevel"` @@ -568,6 +880,66 @@ func (a *IntelligenceAgent) analyzeMatrixActivity(data *string) (*string, error) } ``` +```typescript AssemblyScript focus={3-54} +class IntelligenceAgent extends Agent { + // ... + private analyzeMatrixActivity(data: string): string | null { + this.publishEvent( + new MissionStarted("Matrix Surveillance Analysis", "HIGH", data.length), + ) + + this.intelReports.push(data) + this.lastContact = Date.now() + + this.publishEvent( + new SurveillanceProgress( + "Processing Matrix surveillance data", + 0.3, + this.intelReports.length, + this.intelReports.length, + ), + ) + + const model = models.getModel("text-generator") + const prompt = `You are a resistance operative in the Matrix. + Analyze patterns from accumulated surveillance reports and provide threat assessment. + Respond in no more than 2 concise sentences.` + const content = + "All Matrix Intelligence:\n" + + this.intelReports.join("\n") + + "\n\nProvide threat assessment:" + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content), + ]) + const analysis = model.invoke(input).choices[0].message.content + + this.threatLevel = Math.min(1, this.intelReports.length / 10) + + if ( + analysis.toLowerCase().includes("critical") || + analysis.toLowerCase().includes("agent smith") + ) { + this.threatLevel = Math.min(this.threatLevel + 0.2, 1) + this.publishEvent(new ThreatDetected("HIGH", this.threatLevel, analysis)) + } + + this.publishEvent( + new MissionCompleted( + "Matrix Surveillance Analysis", + this.threatLevel, + this.intelReports.length, + "SUCCESS", + ), + ) + + return `Matrix surveillance complete:\n${analysis}\n\n(Threat level: ${this.threatLevel} based on ${this.intelReports.length} reports)` + } +} +``` + + + ### Event-driven operational patterns This streaming capability enables sophisticated real-time operational patterns: @@ -611,7 +983,9 @@ curl -N -H "accept: text/event-stream" \ You can also poll agent status directly through dedicated functions: -```go + + +```go Go func CheckMissionProgress(agentId string) (*MissionStatus, error) { res, err := agents.SendMessage(agentId, "get_status") if err != nil || res == nil { @@ -633,10 +1007,22 @@ type MissionStatus struct { } ``` +```typescript AssemblyScript +export function checkMissionProgress(agentId: string): MissionStatus | null { + const res = agents.sendMessage(agentId, "get_status") + if (!res) return null + return JSON.parse(res) +} +``` + + + The agent tracks its operational status using the mission state we defined earlier: -```go + + +```go Go func (a *IntelligenceAgent) getOperationalStatus() (*string, error) { status := MissionStatus{ Phase: "Standby", @@ -667,6 +1053,42 @@ func (a *IntelligenceAgent) getOperationalStatus() (*string, error) { } ``` +```typescript AssemblyScript focus={3-30} +class IntelligenceAgent extends Agent { + // ... + private getOperationalStatus(): string { + const status = new MissionStatus() + + if (this.currentMission && this.missionLog.length > 0) { + let progress = this.missionLog.length / 4.0 + if (progress > 1.0) progress = 1.0 + + const now = Date.now() + const endTime = + this.currentMission!.startTime + this.currentMission!.duration + const remaining = endTime > u64(now) ? endTime - now : 0 + const estimatedSeconds = (remaining / 1000) + + status.phase = this.currentMission!.name + status.progress = progress + status.currentTask = this.missionLog[this.missionLog.length - 1] + status.isComplete = this.currentMission!.complete + status.estimatedTimeRemaining = estimatedSeconds + } else { + status.phase = "Standby" + status.progress = 1.0 + status.currentTask = "Awaiting mission directives in the Matrix" + status.isComplete = true + status.estimatedTimeRemaining = 0 + } + + return JSON.stringify(status) + } +} +``` + + + Your client can either poll this status endpoint via GraphQL or subscribe to real-time events for instant updates: