Cortex

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=20

8. 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.

On this page