Answers a yes/no question about input text — returns true or false.
| Field | Type | Description |
|---|---|---|
Input |
*string |
Text to evaluate |
| Field | Type | Description |
|---|---|---|
Result |
bool |
True if the predicate holds, false otherwise |
Reasoning is captured by WithReasoningLog — no graph output needed.
| Key | Type | Default | Description |
|---|---|---|---|
predicate |
string |
required | Yes/no question, e.g. "Does this mention a payment?" |
max_retries |
string |
"3" | Number of retries on parse error |
Ideal for workflow conditions. The bool Result feeds directly into predicate-driven skip logic. Downstream nodes whose skip condition depends on this wire will be skipped or executed accordingly without any adapter op.
Write tight predicates. A focused yes/no question ("Does this email contain a refund request?") is more reliable than a broad or compound predicate. If you need multiple checks, use multiple AIBoolOp nodes in parallel.
Spam filter: classifies the input message and generates a support response only when the message is clean.
package main
import (
"bufio"
"context"
"encoding/json"
"fmt"
"log"
"os"
"strings"
"time"
"github.com/akennis/sparsi-go/library"
_ "github.com/akennis/dagor/operator/builtin"
"github.com/panjf2000/ants/v2"
"github.com/akennis/dagor"
"github.com/akennis/dagor/graph"
"github.com/akennis/dagor/predicate"
)
func registerPredicates() {
if err := predicate.Register("message_not_spam", func(inputs map[string]any) bool {
v, ok := inputs["is_spam"].(*bool)
return ok && v != nil && !*v
}); err != nil {
log.Fatalf("register predicate: %v", err)
}
}
func buildGraph(message string) (*graph.Graph, error) {
library.RegisterConst("user_message", message)
return graph.NewBuilder("spam_filter").
Vertex("msg_src").Op("user_message").
Output("Result", "user_message").
Vertex("check_spam").Op("AIBoolOp").
Params(map[string]string{
"predicate": "Does this message contain spam, abusive language, or policy violations?",
}).
Input("Input", "user_message").
Output("Result", "is_spam").
// Only runs when is_spam == false.
Vertex("process_message").Op("AIComputeStringToStringOp").
Params(map[string]string{
"operation": "Generate a helpful support response to this customer message",
}).
Condition("message_not_spam").
ConditionInput("is_spam").
Input("Input", "user_message").
Output("Result", "response_text").
Build()
}
func main() {
fmt.Print("Message: ")
line, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
log.Fatalf("reading input: %v", err)
}
message := strings.TrimSpace(line)
if message == "" {
log.Fatal("message cannot be empty")
}
registerPredicates()
g, err := buildGraph(message)
if err != nil {
log.Fatalf("build graph: %v", err)
}
pool, err := ants.NewPool(10)
if err != nil {
log.Fatalf("create pool: %v", err)
}
defer pool.Release()
eng, err := dagor.NewEngine(g, pool)
if err != nil {
log.Fatalf("create engine: %v", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
if err := eng.Run(ctx); err != nil {
log.Fatalf("run graph: %v", err)
}
output := map[string]any{}
if raw, ok := eng.GetOutput("is_spam"); ok {
if v, ok := raw.(*bool); ok && v != nil {
output["is_spam"] = *v
}
}
if !eng.VertexSkipped("process_message") {
if raw, ok := eng.GetOutput("response_text"); ok {
if v, ok := raw.(*string); ok && v != nil {
output["response"] = *v
}
}
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(output); err != nil {
log.Fatalf("encode output: %v", err)
}
}