4  Agent Configuration

This chapter describes the stable configuration surface area of the Agent primitive.

An Agent is stateful and multi-turn: it can call tools, accumulate message history, and iterate until done. That flexibility is powerful, but it also means the configuration is where most reliability and safety decisions are made.

4.1 Declaring an Agent

Agents are declared at top level using assignment syntax:

local done = require("tactus.tools.done")

lookup_customer = Tool {
  description = "Look up a customer record",
  input = { id = field.string{required = true} },
  function(args)
    return {id = args.id, plan = "pro"}
  end
}

triage_agent = Agent {
  model = "openai/gpt-4o-mini",
  system_prompt = [[
You triage support messages into labels: billing, account, bug, other.
Use lookup_customer when you need account context. Call done when finished.
  ]],
  tools = {lookup_customer, done}
}

Notes:

  • Prefer assignment syntax (triage_agent = Agent { ... }). Curried syntax (Agent "triage_agent" { ... }) is deprecated.
  • Agents are callable: you invoke the variable like a function (see Chapter 05).

4.2 Provider and Model Selection

Agent declarations typically specify:

  • provider: the provider backend name (e.g. "openai", "bedrock", "google")
  • model: the provider-specific model identifier

In many codebases, you will centralize provider/model choice in environment configuration, and keep the agent declaration focused on:

  • the system prompt (role + constraints)
  • tool access
  • deterministic orchestration patterns (per-turn tool control, bounded loops, explicit stop conditions)

4.3 System Prompt (and Template Variables)

system_prompt is the instruction that frames every agent turn.

Tactus supports template variables inside prompts (for example: {input.customer_id}), so you can parameterize a single agent configuration for different procedure inputs.

Best practice:

  • Put rules in the system prompt (what to do, what not to do, required invariants).
  • Put data in the runtime message/context (so it is easy to test and reason about).

4.4 Tool Access (and Capability Boundaries)

Tools are an agent’s capability boundary.

4.4.1 tools = {...}

The tools field defines the default set of tools and toolsets available to an agent.

You can pass:

  • individual Tool { ... } declarations
  • Toolset { ... } declarations (group tools under a single handle)
  • stdlib toolsets by string name (e.g. "filesystem") when supported by your runtime configuration

4.5 Generation and Execution Parameters

Agents support a small set of generation parameters that you can set on the declaration, and override per call when needed.

Common fields:

  • temperature (default: 0.7)
  • max_tokens (optional)
  • module (default: "Raw", case-insensitive; also supports "Predict" and "ChainOfThought")

Per-call overrides are documented in Chapter 05.

4.6 Initial Message

Some workflows benefit from sending an initial_message on the first turn (for example: bootstrapping a plan). Prefer explicit procedure calls when possible; use initial_message only when it simplifies a pattern that is otherwise awkward.