Full Example
Build a customer-support agent end-to-end — skills, traits, behaviors, persona, agent config, engine wiring, and API usage.
This guide builds a complete Cortex agent from scratch — a customer-support bot with a persona, skills, traits, and behaviors — using PostgreSQL for persistence.
1. Set up the engine
package main
import (
"context"
"database/sql"
"fmt"
"log"
"os"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
"github.com/xraph/cortex"
"github.com/xraph/cortex/engine"
pgstore "github.com/xraph/cortex/store/postgres"
)
func main() {
ctx := context.Background()
// Connect to PostgreSQL
sqldb := sql.OpenDB(pgdriver.NewConnector(
pgdriver.WithDSN(os.Getenv("DATABASE_URL")),
))
db := bun.NewDB(sqldb, pgdialect.New())
// Create the composite store
st := pgstore.New(db)
// Build the engine
eng, err := engine.New(
engine.WithStore(st),
engine.WithConfig(cortex.Config{
DefaultModel: "gpt-4o",
DefaultMaxSteps: 25,
DefaultMaxTokens: 4096,
DefaultTemperature: 0.7,
DefaultReasoningLoop: "react",
}),
)
if err != nil {
log.Fatal(err)
}
// Run migrations
if err := st.Migrate(ctx); err != nil {
log.Fatal("migrate:", err)
}
// Set tenant scope
ctx = cortex.WithTenant(ctx, "acme-corp")
ctx = cortex.WithApp(ctx, "support-bot")
buildAgent(ctx, eng)
}2. Create a skill
Skills define what an agent can do — the tools it can use and the knowledge it can reference.
import "github.com/xraph/cortex/skill"
func buildAgent(ctx context.Context, eng *engine.Engine) {
// Create a "customer-support" skill with two tool bindings
supportSkill := &skill.Skill{
AppID: "support-bot",
Name: "customer-support",
Description: "Handle customer inquiries using CRM tools",
Tools: []skill.ToolBinding{
{
ToolName: "lookup_order",
Mastery: skill.Expert,
Guidance: "Always verify the order ID format before lookup",
},
{
ToolName: "create_ticket",
Mastery: skill.Proficient,
Guidance: "Classify ticket priority based on customer sentiment",
},
},
Knowledge: []skill.KnowledgeRef{
{Source: "policies://return-policy", InjectMode: "always", Priority: 1},
{Source: "policies://warranty", InjectMode: "on_demand", Priority: 2},
},
SystemPromptFragment: "You are an expert support agent. Always be empathetic.",
DefaultProficiency: skill.Proficient,
}
if err := eng.CreateSkill(ctx, supportSkill); err != nil {
log.Fatal("create skill:", err)
}
fmt.Println("created skill:", supportSkill.ID)3. Create a trait
Traits define personality dimensions — bipolar axes that shape agent behavior.
import "github.com/xraph/cortex/trait"
// Create an "empathy" trait
empathyTrait := &trait.Trait{
AppID: "support-bot",
Name: "empathy",
Description: "Ability to understand and share customer feelings",
Category: trait.Emotional,
Dimensions: []trait.Dimension{
{
Name: "emotional-awareness",
LowLabel: "detached",
HighLabel: "empathetic",
Value: 0.85,
},
{
Name: "patience",
LowLabel: "hurried",
HighLabel: "patient",
Value: 0.9,
},
},
Influences: []trait.Influence{
{Target: "tone", Value: "warm and understanding", Weight: 0.8},
{Target: "vocabulary", Value: "supportive phrases", Weight: 0.6},
},
}
if err := eng.CreateTrait(ctx, empathyTrait); err != nil {
log.Fatal("create trait:", err)
}
fmt.Println("created trait:", empathyTrait.ID)4. Create a behavior
Behaviors define automatic reactions to triggers — like habits an agent follows.
import "github.com/xraph/cortex/behavior"
escalationBehavior := &behavior.Behavior{
AppID: "support-bot",
Name: "auto-escalate",
Description: "Escalate angry customers to a human agent",
Priority: 10,
Triggers: []behavior.Trigger{
{Type: behavior.SentimentBelow, Pattern: "0.3"},
{Type: behavior.KeywordMatch, Pattern: "speak to manager|supervisor|escalate"},
},
Actions: []behavior.Action{
{Type: behavior.ModifyTone, Target: "tone", Value: "extra empathetic"},
{Type: behavior.InjectPrompt, Value: "Acknowledge the customer's frustration before proceeding."},
},
}
if err := eng.CreateBehavior(ctx, escalationBehavior); err != nil {
log.Fatal("create behavior:", err)
}
fmt.Println("created behavior:", escalationBehavior.ID)5. Create a persona
A persona composes skills, traits, and behaviors into a coherent identity.
import (
"github.com/xraph/cortex/persona"
"github.com/xraph/cortex/cognitive"
"github.com/xraph/cortex/communication"
"github.com/xraph/cortex/perception"
)
supportPersona := &persona.Persona{
AppID: "support-bot",
Name: "helpful-agent",
Description: "A warm, knowledgeable customer support agent",
Identity: "I am a customer support specialist who genuinely cares about solving problems.",
Skills: []persona.SkillAssignment{
{SkillName: "customer-support", Proficiency: skill.Expert},
},
Traits: []persona.TraitAssignment{
{TraitName: "empathy", DimensionValues: map[string]float64{
"emotional-awareness": 0.85,
"patience": 0.9,
}},
},
Behaviors: []string{"auto-escalate"},
CognitiveStyle: &cognitive.Style{
Phases: []cognitive.Phase{
{Name: "understand", Strategy: cognitive.Analytical, Prompt: "Understand the customer's issue"},
{Name: "resolve", Strategy: cognitive.Creative, Prompt: "Find the best solution"},
{Name: "confirm", Strategy: cognitive.Methodical, Prompt: "Verify the customer is satisfied"},
},
},
CommunicationStyle: &communication.Style{
Tone: "warm",
Formality: "professional-casual",
Verbosity: "concise",
TechnicalLevel: "low",
EmojiUsage: "minimal",
PreferredFormat: "conversational",
AdaptToUser: true,
},
Perception: &perception.Model{
AttentionFilter: perception.AttentionFilter{
Name: "support-focus",
Keywords: []string{"order", "return", "refund", "complaint", "issue"},
},
ContextWindow: "recent",
DetailOrientation: "high",
},
}
if err := eng.CreatePersona(ctx, supportPersona); err != nil {
log.Fatal("create persona:", err)
}
fmt.Println("created persona:", supportPersona.ID)6. Create an agent
The agent config ties everything together — specifying the model, persona, and execution parameters.
import "github.com/xraph/cortex/agent"
agentCfg := &agent.Config{
AppID: "support-bot",
Name: "support-agent",
Description: "Primary customer support agent",
SystemPrompt: "You are a helpful customer support agent for Acme Corp.",
Model: "gpt-4o",
PersonaRef: "helpful-agent",
MaxSteps: 15,
MaxTokens: 4096,
Temperature: 0.7,
}
if err := eng.CreateAgent(ctx, agentCfg); err != nil {
log.Fatal("create agent:", err)
}
fmt.Println("created agent:", agentCfg.ID)
}7. Run via API
Once the engine is wired up with the HTTP API, you can interact through REST:
# List agents
curl http://localhost:8080/cortex/agents
# Run the agent
curl -X POST http://localhost:8080/cortex/agents/support-agent/run \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: acme-corp" \
-H "X-App-ID: support-bot" \
-d '{"input": "I want to return order #12345, the product arrived damaged"}'
# Check run status
curl http://localhost:8080/cortex/runs/{run_id}
# Stream a run
curl -N -X POST http://localhost:8080/cortex/agents/support-agent/stream \
-H "Content-Type: application/json" \
-d '{"input": "What is your return policy?"}'
# View conversation history
curl http://localhost:8080/cortex/agents/support-agent/conversation?limit=208. Wiring with Forge
For production, use the Forge extension to get automatic lifecycle management:
import (
"github.com/xraph/forge"
"github.com/xraph/cortex/extension"
pgstore "github.com/xraph/cortex/store/postgres"
)
func main() {
app := forge.New()
cortexExt := extension.New(
extension.WithStore(pgstore.New(bunDB)),
)
app.RegisterExtension(cortexExt)
app.Run()
}The Forge extension handles migrations, route registration, health checks, and graceful shutdown automatically. See the Forge Extension guide for details.