Skip to content

Programmatic API

Hector provides a pure programmatic API for building agents directly in Go code. This API is the foundation of Hector—the configuration system is built on top of it, not the other way around.

When to Use Programmatic API

Use the programmatic API when you need:

  • Custom Logic: Dynamic agent creation based on runtime conditions
  • Integration: Embedding agents into existing Go applications
  • Advanced Control: Fine-grained control over agent construction
  • Testing: Programmatic agent creation for unit tests
  • Library Development: Building higher-level abstractions on top of Hector

For simple use cases, YAML configuration is often easier.


Architecture

┌─────────────────────────────────────────────────────────────┐
│         Pure Programmatic API (Foundation)                  │
│  Chained builders, no config concepts, direct construction │
│                                                              │
│  AgentBuilder → Agent → Runtime                             │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │ Used by
                            │
┌─────────────────────────────────────────────────────────────┐
│         Config System (Convenience Layer)                    │
│  YAML/JSON → Config → Uses Programmatic API → Agents        │
│                                                              │
│  config.Config → AgentBuilder → Agent → Runtime               │
└─────────────────────────────────────────────────────────────┘

Key Principle: The configuration system uses the programmatic API internally. All agent construction flows through the programmatic API.


Quick Start

Basic Agent

package main

import (
    "github.com/kadirpekel/hector/pkg/hector"
    "github.com/kadirpekel/hector/pkg/tools"
)

func main() {
    // Build LLM provider
    llm, err := hector.NewLLMProvider("openai").
        Model("gpt-4o-mini").
        APIKeyFromEnv("OPENAI_API_KEY").
        Temperature(0.7).
        Build()
    if err != nil {
        panic(err)
    }

    // Build reasoning strategy
    reasoning, err := hector.NewReasoning("chain-of-thought").
        MaxIterations(100).
        EnableStreaming(true).
        Build()
    if err != nil {
        panic(err)
    }

    // Build working memory
    workingMemory, err := hector.NewWorkingMemory("summary_buffer").
        Budget(2000).
        Threshold(0.8).
        WithLLMProvider(llm).
        Build()
    if err != nil {
        panic(err)
    }

    // Build agent
    agent, err := hector.NewAgent("assistant").
        WithName("Assistant").
        WithDescription("A helpful AI assistant").
        WithLLMProvider(llm).
        WithReasoningStrategy(reasoning).
        WithWorkingMemory(workingMemory).
        WithSystemPrompt("You are a helpful assistant.").
        WithTools(
            tools.NewFileWriterTool(nil),
            tools.NewReadFileTool(nil),
        ).
        Build()
    if err != nil {
        panic(err)
    }

    fmt.Printf("Built agent: %s (%s)\n", agent.GetID(), agent.GetName())
}

Core Concepts

1. Chained Builders

All builders use a fluent, chainable API:

agent, err := hector.NewAgent("my-agent").
    WithName("My Agent").
    WithDescription("Does amazing things").
    WithLLMProvider(llm).
    WithReasoningStrategy(reasoning).
    Build()

2. Component Builders

Build components independently and reuse them:

// Build once, use many times
llm, _ := hector.NewLLMProvider("openai").
    Model("gpt-4o").
    APIKeyFromEnv("OPENAI_API_KEY").
    Build()

// Use in multiple agents
agent1, _ := hector.NewAgent("agent1").WithLLMProvider(llm).Build()
agent2, _ := hector.NewAgent("agent2").WithLLMProvider(llm).Build()

3. Direct Construction

No configuration files needed—everything is constructed directly:

// No YAML, no config files—pure Go code
agent, err := hector.NewAgent("custom").
    WithLLMProvider(llm).
    WithReasoningStrategy(reasoning).
    Build()

Building Components

LLM Providers

// OpenAI
llm, err := hector.NewLLMProvider("openai").
    Model("gpt-4o").
    APIKey("sk-...").
    Temperature(0.7).
    MaxTokens(4000).
    Build()

// Anthropic
llm, err := hector.NewLLMProvider("anthropic").
    Model("claude-3-5-sonnet-20241022").
    APIKeyFromEnv("ANTHROPIC_API_KEY").
    Temperature(0.8).
    Build()

// Ollama (local)
llm, err := hector.NewLLMProvider("ollama").
    Model("llama2").
    Host("localhost:11434").
    Build()

Reasoning Strategies

// Chain-of-Thought
reasoning, err := hector.NewReasoning("chain-of-thought").
    MaxIterations(100).
    EnableStreaming(true).
    ShowTools(true).
    ShowThinking(true).
    Build()

// Supervisor (for multi-agent)
reasoning, err := hector.NewReasoning("supervisor").
    MaxIterations(10).
    EnableStreaming(true).
    Build()

Memory Strategies

// Summary Buffer
memory, err := hector.NewWorkingMemory("summary_buffer").
    Budget(2000).
    Threshold(0.8).
    Target(0.6).
    WithLLMProvider(llm).
    Build()

// Buffer Window
memory, err := hector.NewWorkingMemory("buffer_window").
    WindowSize(10).
    Build()

// Sliding Window
memory, err := hector.NewWorkingMemory("sliding_window").
    Budget(4000).
    Build()

Long-Term Memory

// Build database
db, err := hector.NewDatabase("qdrant").
    Host("localhost").
    Port(6333).
    APIKey("...").
    Build()

// Build embedder
embedder, err := hector.NewEmbedder("openai").
    Model("text-embedding-3-small").
    APIKeyFromEnv("OPENAI_API_KEY").
    Build()

// Build long-term memory
longTerm, config, err := hector.NewLongTermMemory().
    Enabled(true).
    Collection("agent_memory").
    StorageScope(memory.StorageScopeAll).
    BatchSize(10).
    AutoRecall(true).
    RecallLimit(5).
    WithDatabase(db).
    WithEmbedder(embedder).
    Build()

Context Service (RAG)

// Build context service for RAG
contextService, err := hector.NewContextService().
    WithDatabase(db).
    WithEmbedder(embedder).
    TopK(5).
    Threshold(0.7).
    IncludeContext(true).
    Build()

Document Stores (RAG)

// Directory-based document store
docStore, err := hector.NewDocumentStore("docs", "directory").
    Path("./docs").
    ChunkSize(800).
    ChunkOverlap(100).
    IncludePatterns([]string{"*.md", "*.txt"}).
    ExcludePatterns([]string{"**/node_modules/**"}).
    WatchChanges(true).
    ExtractMetadata(true).
    MetadataLanguages([]string{"go"}).
    Build()

// Use with context service
contextService, err := hector.NewContextService().
    WithDatabase(db).
    WithEmbedder(embedder).
    WithDocumentStoreBuilder(hector.NewDocumentStore("docs", "directory").
        Path("./docs").
        ChunkSize(800)).
    TopK(5).
    Build()

// SQL-based document store
sqlBuilder := hector.NewDocumentStoreSQL("mydb").
    Driver("postgres").
    Host("localhost").
    Port(5432).
    Username("user").
    Password("pass")

tableBuilder := hector.NewDocumentStoreSQLTable("articles", []string{"title", "content"}, "id").
    UpdatedColumn("updated_at").
    MetadataColumns([]string{"author", "category"})

sqlStore, err := hector.NewDocumentStore("articles", "sql").
    WithSQLBuilder(sqlBuilder).
    WithSQLTableBuilder(tableBuilder).
    ChunkSize(1000).
    Build()

// API-based document store
authBuilder := hector.NewDocumentStoreAPIAuth("bearer").
    Token("my-api-token")

endpointBuilder := hector.NewDocumentStoreAPIEndpoint("/api/articles").
    ContentField("content").
    IDField("id").
    UpdatedField("updated_at").
    WithAuthBuilder(authBuilder)

apiBuilder := hector.NewDocumentStoreAPI("https://api.example.com").
    WithAuthBuilder(authBuilder).
    WithEndpointBuilder(endpointBuilder)

apiStore, err := hector.NewDocumentStore("api-docs", "api").
    WithAPIBuilder(apiBuilder).
    ChunkSize(800).
    Build()

Task Service

// In-memory task service
taskService, err := hector.NewTaskService().
    Backend("memory").
    WorkerPool(10).
    InputTimeout(600).
    Build()

// SQL task service with HITL and checkpoint
taskService, err := hector.NewTaskService().
    Backend("sql").
    WorkerPool(10).
    InputTimeout(600).
    Timeout(3600).
    SQLConfig().
        Driver("sqlite").
        Database("./tasks.db").
        Build().
    HITL().
        Mode("async").  // Async HITL (requires session_store)
        Build().
    Checkpoint().
        Enabled(true).
        Strategy("hybrid").
        Interval().
            EveryNIterations(5).
            Build().
        Recovery().
            AutoResume(true).
            ResumeTimeout(3600).
            Build().
        Build().
    Build()

Session Service

// In-memory session service
sessionService, err := hector.NewSessionService().
    Backend("memory").
    Build()

// SQL session service
sessionService, err := hector.NewSessionService().
    Backend("sql").
    WithSQLConfig(&config.SQLConfig{
        Driver: "postgres",
        DSN:    "postgres://user:pass@localhost/db",
    }).
    Build()

Observability (Tracing & Metrics)

// Configure observability programmatically
obsConfig, err := hector.NewObservability().
    EnableMetrics(true).
    WithTracing(hector.NewTracing().
        Enable(true).
        EndpointURL("http://jaeger:4317").
        SamplingRate(0.1).  // 10% sampling
        ServiceName("my-hector-app")).
    Build()

if err != nil {
    log.Fatal(err)
}

// Initialize observability manager
obsMgr := observability.NewManager(obsConfig)
if err := obsMgr.Initialize(context.Background()); err != nil {
    log.Fatal(err)
}

// Use tracer
tracer := obsMgr.GetTracer("my-component")
ctx, span := tracer.Start(context.Background(), "my-operation")
defer span.End()

// Metrics are automatically collected

Building Agents

Complete Agent Example

agent, err := hector.NewAgent("research-assistant").
    WithName("Research Assistant").
    WithDescription("Helps with research tasks").

    // LLM
    WithLLMProvider(llm).

    // Reasoning
    WithReasoningStrategy(reasoning).

    // Memory
    WithWorkingMemory(workingMemory).
    WithLongTermMemory(longTermMemory, longTermConfig).

    // Context (RAG)
    WithContext(contextService).

    // Tasks
    WithTask(taskService).

    // Sessions
    WithSession(sessionService).

    // Prompts
    WithSystemPrompt("You are a research assistant.").
    WithPromptSlots(&reasoning.PromptSlots{
        SystemRole:   "You are an expert researcher.",
        Instructions: "Always cite sources.",
        UserGuidance: "Be thorough and accurate.",
    }).

    // Tools
    WithTools(
        tools.NewFileWriterTool(nil),
        tools.NewReadFileTool(nil),
        tools.NewSearchTool(nil),
    ).

    // A2A Configuration
    WithA2ACard(hector.NewA2ACardBuilder(nil).
        Version("1.0.0").
        InputModes([]string{"text/plain", "application/json"}).
        OutputModes([]string{"text/plain", "application/json"}).
        PreferredTransport("json-rpc").
        Build()).

    // Security
    WithSecurity(hector.NewSecurityBuilder(nil).
        JWKSURL("https://auth.example.com/.well-known/jwks.json").
        Issuer("https://auth.example.com").
        Audience("hector-api").
        Build()).

    Build()

Combining Config and Programmatic

You can mix agents built from config and programmatic agents:

// Load config
cfg, _ := config.LoadConfig(config.LoaderOptions{
    Path: "configs/agents.yaml",
})

// Build agents from config (uses programmatic API internally)
configBuilder, _ := hector.NewConfigAgentBuilder(cfg)
configAgents, _ := configBuilder.BuildAllAgents()

// Build agent programmatically
programmaticAgent, _ := hector.NewAgent("custom").
    WithLLMProvider(llm).
    WithReasoningStrategy(reasoning).
    Build()

// Combine in runtime
runtime, _ := runtime.NewRuntimeBuilder().
    WithAgents(configAgents).      // From config
    WithAgent(programmaticAgent).   // Programmatic
    Start()

Runtime Builder

Build a runtime programmatically:

runtime, err := runtime.NewRuntimeBuilder().
    WithAgent(agent1).
    WithAgent(agent2).
    WithAgents(map[string]*agent.Agent{
        "agent3": agent3,
        "agent4": agent4,
    }).
    Start()

Best Practices

1. Reuse Components

Build components once and reuse:

// Build shared components
llm, _ := hector.NewLLMProvider("openai").Model("gpt-4o").APIKeyFromEnv("OPENAI_API_KEY").Build()
reasoning, _ := hector.NewReasoning("chain-of-thought").Build()

// Reuse in multiple agents
agent1, _ := hector.NewAgent("agent1").WithLLMProvider(llm).WithReasoningStrategy(reasoning).Build()
agent2, _ := hector.NewAgent("agent2").WithLLMProvider(llm).WithReasoningStrategy(reasoning).Build()

2. Error Handling

Always check errors:

llm, err := hector.NewLLMProvider("openai").Build()
if err != nil {
    return fmt.Errorf("failed to build LLM: %w", err)
}

3. Builder Pattern

Use the fluent builder pattern consistently:

// Good: Chainable
agent, _ := hector.NewAgent("id").
    WithName("Name").
    WithLLMProvider(llm).
    Build()

// Avoid: Multiple assignments
builder := hector.NewAgent("id")
builder.WithName("Name")
builder.WithLLMProvider(llm)
agent, _ := builder.Build()

4. Component Lifecycle

Components are independent—build them in any order:

// Order doesn't matter
llm, _ := hector.NewLLMProvider("openai").Build()
reasoning, _ := hector.NewReasoning("chain-of-thought").Build()
memory, _ := hector.NewWorkingMemory("summary_buffer").Build()

// Combine when building agent
agent, _ := hector.NewAgent("id").
    WithLLMProvider(llm).
    WithReasoningStrategy(reasoning).
    WithWorkingMemory(memory).
    Build()

Next Steps