SageLang Agent & Chatbot Guide

June 14, 2026 · View on GitHub

Build autonomous AI agents and conversational chatbots using SageLang's agent and chat frameworks with the SageLLM model backend.

Agent Framework (lib/agent/)

Quick Start

import agent.core

proc my_llm(prompt):
    return "ANSWER: Hello!"

let a = core.create("my-agent", "You are helpful.", my_llm)
core.add_tool(a, "greet", "Say hello", "name", proc(args): return "Hi " + args)
let answer = core.run(a, "Greet the user")
print answer

ReAct Loop

The agent follows a ReAct (Reason + Act) pattern:

  1. Observe: Receive user input
  2. Think: LLM generates reasoning (THOUGHT:)
  3. Act: LLM calls a tool (TOOL: name(args))
  4. Reflect: Process tool result, decide next step
  5. Answer: LLM provides final answer (ANSWER:)

Multi-Agent Routing

import agent.router

let r = router.create_router()
router.register(r, code_agent, ["code", "programming", "bug"])
router.register(r, docs_agent, ["documentation", "explain", "guide"])
router.set_default(r, "code_agent")

let agent = router.route(r, "Fix this bug in the parser")
core.run(agent, "Fix this bug in the parser")

Task Planning

import agent.planner

let plan = planner.create_plan("Refactor the lexer")
planner.add_step(plan, "Read current lexer code", "read_file", "src/c/lexer.c", nil)
planner.add_step(plan, "Analyze structure", "analyze_code", "", [0])
planner.add_step(plan, "Write improved version", "write_file", "", [1])
planner.execute_plan(plan, my_agent)

Grammar-Constrained Decoding (agent.grammar)

Enforce strict output formats to prevent malformed tool calls or invalid JSON:

import agent.grammar

# Wrap an LLM to only output valid JSON
let json_llm = grammar.constrained_llm(my_llm, "json", 3)

# Wrap for strict ReAct tool call syntax
let tool_llm = grammar.constrained_llm(my_llm, "tool_call", 3)

Program-Aided Reasoning (agent.sandbox)

Allow agents to execute Sage code blocks for deterministic calculations:

import agent.sandbox

let par = sandbox.create_par_agent("MathAgent", my_llm)
let result = sandbox.par_query(par, "What is 12345 * 6789?")
if result["code_executed"]:
    print "Calculated: " + result["result"]

Tree of Thoughts (agent.tot)

Solve complex problems by searching through reasoning chains with rollbacks:

import agent.tot

let solver = tot.create_solver(my_evaluator, 5, 3)
let path = tot.best_first_search(solver, my_llm, "Initial problem", is_goal)
print tot.format_path(path)

Semantic Routing (agent.semantic_router)

Fast command dispatch that bypasses the LLM for known keywords:

import agent.semantic_router

let r = semantic_router.create_router(0.7)
semantic_router.add_sage_routes(r)
semantic_router.set_fallback(r, my_llm)

let result = semantic_router.route(r, "run the tests")
print result["result"] # Dispatched to _rt_test

Chatbot Framework (lib/chat/)

Quick Start

import chat.bot
import chat.persona

let b = bot.create("", "", my_llm)
persona.apply_persona(b, persona.sage_developer())
print bot.greet(b)
let response = bot.respond(b, "How do I write a for loop?")
print response

Built-in Personas

PersonaUse Case
sage_developer()Sage code help (default)
code_reviewer()Code review
teacher()Programming education
debugger()Bug hunting
architect()System design
assistant()General help

Intent Recognition

bot.add_intent(b, "greeting", ["hello", "hi", "hey"], proc(msg, conv):
    return "Hello! How can I help?")
bot.add_intent(b, "farewell", ["bye", "goodbye"], proc(msg, conv):
    return "Goodbye!")

Sessions

import chat.session

let store = session.create_store()
let s = session.new_session(store, "SageDev")
session.add_turn(s, "What is Sage?", "Sage is a systems language.")
print session.export_text(s)
session.save_session(s, "chat_log.txt")

SageLLM Chatbot v3 (models/chatbots/sagellm_chatbot.sage)

The SageLLM chatbot is a self-contained binary generated by the build pipeline. All features — knowledge base, personas, memory, chain-of-thought, and planning — are implemented inline without external module imports, making it compatible with all compiler backends.

Building

# LLVM backend (recommended, 124KB binary)
sage --compile-llvm models/chatbots/sagellm_chatbot.sage -o sagellm_chat

# C backend (113KB binary)
sage --compile models/chatbots/sagellm_chatbot.sage -o sagellm_chat

# Run
./sagellm_chat

Because the chatbot has no external module dependencies, both --compile-llvm and --compile produce a fully standalone executable.

Build Pipeline

The chatbot source is generated automatically by the 12-phase SageLLM build pipeline:

sage models/tools/build_sagellm.sage

This runs data collection, model init, pre-training, LoRA fine-tuning, DPO, RAG, Engram memory, quantization, chatbot generation, GGUF export, visualization, and summary — producing models/chatbots/sagellm_chatbot.sage as its output.

Knowledge & Capabilities

  • 51 semantic facts covering Sage language features, syntax, and idioms
  • 8 procedural skills: code generation, debugging, explanation, review, optimization, formatting, testing, documentation
  • 20 topic domains: syntax, types, functions, classes, modules, stdlib, compiler, LLVM, GPU, agents, and more

Commands

CommandDescription
quitExit the chatbot
memoryShow current session memory
remember <fact>Store a fact in persistent memory
recall <topic>Retrieve stored facts on a topic
think <question>Display visible chain-of-thought reasoning
plan <goal>Generate a 9-step development DAG
personasList available personas
helpShow command reference

Personas

PersonaFocus
SageDev (default)Sage language development, code generation
TeacherStep-by-step explanations, examples
DebuggerError diagnosis, root-cause analysis
ArchitectSystem design, component structure

Features

  • Chain-of-thought reasoning: The think command exposes the internal reasoning chain before producing a final answer.
  • Persistent memory: remember and recall store and retrieve facts across the session.
  • Development planning: plan generates a directed acyclic graph of 9 ordered steps for a given goal.
  • Persona switching: Type a persona name or use personas to switch reasoning style mid-session.

Production Agent Architecture

Supervisor-Worker Pattern

import agent.supervisor

# Create specialist workers
proc code_llm(task): return "proc hello(): print 42"
proc test_llm(task): return "# EXPECT: 42"

let coder = supervisor.create_worker("coder", "Write Sage code", code_llm, [])
let tester = supervisor.create_worker("tester", "Write tests", test_llm, [])

# Create supervisor (control plane)
let sup = supervisor.create_supervisor("lead", code_llm)
supervisor.add_worker(sup, coder)
supervisor.add_worker(sup, tester)

# Define workflow with steps
supervisor.add_step(sup, "Write the function", "coder", nil, nil)
supervisor.add_step(sup, "Write tests for it", "tester", nil, nil)

# Execute (retries on failure, self-healing with error context)
let status = supervisor.run_workflow(sup)
print supervisor.workflow_status(sup)

Verification Loops (Critic)

import agent.critic

# Rule-based validator
let v = critic.create_validator()
critic.add_rule(v, "not_empty", critic.rule_not_empty)
critic.add_rule(v, "length", critic.make_length_rule(10, 5000))
critic.add_rule(v, "has_proc", critic.make_contains_rule(["proc"]))

let result = critic.validate(v, output, {})
if not result["valid"]:
    print result["error_summary"]  # bounces back to worker

# LLM critic for semantic review
let c = critic.create_critic("reviewer", review_llm, "code quality and correctness")
let review = critic.review(c, task, output)
if not review["approved"]:
    # Append feedback for self-correction
    task = task + " Feedback: " + review["feedback"]

Typed Tool Interfaces (Schema)

import agent.schema

# Define strict tool schemas
let read_schema = schema.tool_schema("read_file", "Read a file",
    [schema.param("path", "string", true, "File path")], "string")

# Registry validates all calls before execution
let reg = schema.create_registry()
schema.register(reg, read_schema, my_read_fn)

# Execute with validation (rejects bad args automatically)
let result = schema.execute(reg, "read_file", {"path": "/tmp/test.sage"})

SFT Trace Collection

import agent.trace

let rec = trace.create_recorder()
trace.begin_trace(rec, "Write a sorting function")
trace.record_thought(rec, "I need quicksort")
trace.record_tool_call(rec, "write_file", "sort.sage", "written")
trace.record_output(rec, "proc quicksort(arr): ...")
trace.end_trace(rec, true)

# Generate training data
let sft_data = trace.to_sft_examples(rec)      # prompt -> completion
let chat_data = trace.to_chat_examples(rec)      # messages format
let dpo_data = trace.to_preference_pairs(rec)    # chosen vs rejected

Module Reference

ModuleImportKey Functions
coreimport agent.corecreate, add_tool, run, call_tool, think, observe, act, build_prompt
toolsimport agent.toolsregister_all, file_read, file_write, code_analyze, code_search
grammarimport agent.grammarconstrained_llm, create_grammar, tool_call_grammar, json_grammar, constrain
sandboximport agent.sandboxcreate_par_agent, par_query, execute_block, is_safe, eval_math
semantic_routerimport agent.semantic_routercreate_router, add_route, add_sage_routes, route, format_stats
totimport agent.totcreate_solver, bfs_search, best_first_search, format_path, stats
plannerimport agent.plannercreate_plan, add_step, execute_plan, format_plan, progress
routerimport agent.routercreate_router, register, route, send_to, create_pipeline
supervisorimport agent.supervisorcreate_supervisor, add_worker, add_step, run_workflow, dispatch, set_state
criticimport agent.criticcreate_validator, add_rule, validate, create_critic, review, verify_loop
schemaimport agent.schematool_schema, param, validate_args, create_registry, register, execute
traceimport agent.tracecreate_recorder, begin_trace, record_step, end_trace, to_sft_examples, to_chat_examples
botimport chat.botcreate, respond, add_intent, set_context, greet, farewell
sessionimport chat.sessioncreate_store, new_session, add_turn, export_text, save_session
personaimport chat.personasage_developer, code_reviewer, teacher, debugger, architect, custom