| name | traigent-optimize-config-space |
| description | Define tuned variables, structural knobs, and configuration spaces for Traigent optimization. Use when setting up parameter search spaces, choosing models/temperatures/prompts, designing task-level text2SQL/RAG/multi-hop knobs, using Range/IntRange/Choices/LogRange types, adding constraints, or using factory presets like Range.temperature(). |
| license | Apache-2.0 |
| metadata | {"author":"Nimrod","version":"1.0.3"} |
Traigent Configuration Space
When to Use
Use this skill when:
- Defining which parameters to optimize (model, temperature, max_tokens, prompts, etc.)
- Choosing between dict-based and typed parameter definitions
- Designing task-level structural knobs for text2SQL, RAG, multi-hop QA, schema
context, retrieval strategy, generation paths, few-shot policies,
self-consistency, or repair policies (see
references/structural-spine.md)
- Using
Range, IntRange, Choices, or LogRange for search spaces
- Adding constraints between parameters (e.g., "if model is gpt-4, temperature must be low")
- Using factory presets like
Range.temperature() or Choices.model()
- Bundling parameters and constraints into a
ConfigSpace object
Quick Start
The simplest way to define a configuration space is with a dictionary passed to configuration_space:
import traigent
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
configuration_space={
"model": ["gpt-4o-mini", "gpt-4o"],
"temperature": [0.1, 0.5, 0.9],
"max_tokens": [256, 512, 1024],
},
)
def my_function(query: str) -> str:
config = traigent.get_config()
...
Lists create categorical choices. Tuples of two numbers create continuous ranges:
configuration_space={
"model": ["gpt-4o-mini", "gpt-4o"],
"temperature": (0.0, 1.0),
"max_tokens": (100, 4096),
"use_cache": [True, False],
}
Boolean knobs: use native [True, False], never ["true", "false"]. A native bool list
works directly in the dict shorthand (above) and as Choices([True, False]); your function reads
it back as a real bool (if config["use_cache"]: ...). Do not string-encode a bool as
["true", "false"]: in Python the string "false" is truthy (bool("false") is True), so a
consumer that does if config["x"]: is silently always True and the False arm of your
search is never exercised — the optimizer reports both points as identical behaviour and you never
learn one was a no-op. If a string encoding is unavoidable (legacy specs), the consumer must
decode explicitly: enabled = config["x"] == "true".
SE-Friendly Typed Parameters
For stronger typing, validation, and constraint support, use the parameter range classes:
from traigent import Range, IntRange, Choices, LogRange
Pass them as keyword arguments directly to the decorator:
import traigent
from traigent import Range, IntRange, Choices
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy", "cost"],
model=Choices(["gpt-4o-mini", "gpt-4o"]),
temperature=Range(0.0, 1.0),
max_tokens=IntRange(100, 4096),
)
def my_function(query: str) -> str:
config = traigent.get_config()
...
Parameter Types
| Class | Use Case | Example |
|---|
Range | Continuous float values | Range(0.0, 1.0) |
IntRange | Integer values | IntRange(100, 4096) |
Choices | Categorical selection | Choices(["gpt-4o-mini", "gpt-4o"]) |
LogRange | Log-scale float values | LogRange(1e-5, 1e-1) |
Range Options
temperature = Range(0.0, 1.0)
temperature = Range(0.0, 1.0, step=0.1)
learning_rate = Range(1e-5, 1e-1, log=True)
temperature = Range(0.0, 1.0, default=0.7)
IntRange Options
max_tokens = IntRange(100, 4096)
batch_size = IntRange(16, 256, step=16)
max_tokens = IntRange(100, 4096, default=512)
LogRange
Convenience class for Range(low, high, log=True). Use for parameters that vary over orders of magnitude:
learning_rate = LogRange(1e-5, 1e-1)
regularization = LogRange(0.001, 10.0)
Choices Options
model = Choices(["gpt-4o-mini", "gpt-4o", "claude-3-5-sonnet-20241022"])
use_cot = Choices([True, False], default=True)
temperature = Choices([0.0, 0.3, 0.7, 1.0])
model = Choices(["gpt-4o-mini", "gpt-4o"], default="gpt-4o-mini")
See references/parameter-types.md for complete API details.
Factory Presets
Each parameter type offers factory methods with sensible defaults for common LLM parameters.
Range Presets
from traigent import Range
temp = Range.temperature()
temp = Range.temperature(conservative=True)
temp = Range.temperature(creative=True)
top_p = Range.top_p()
freq_pen = Range.frequency_penalty()
pres_pen = Range.presence_penalty()
threshold = Range.similarity_threshold()
mmr = Range.mmr_lambda()
overlap = Range.chunk_overlap_ratio()
IntRange Presets
from traigent import IntRange
tokens = IntRange.max_tokens()
tokens = IntRange.max_tokens(task="short")
tokens = IntRange.max_tokens(task="long")
k = IntRange.k_retrieval()
k = IntRange.k_retrieval(max_k=20)
chunk = IntRange.chunk_size()
overlap = IntRange.chunk_overlap()
few_shot = IntRange.few_shot_count()
batch = IntRange.batch_size()
Choices Presets
from traigent import Choices
model = Choices.model()
model = Choices.model(provider="openai", tier="fast")
model = Choices.model(provider="anthropic", tier="quality")
strategy = Choices.prompting_strategy()
ctx_fmt = Choices.context_format()
retriever = Choices.retriever_type()
embedding = Choices.embedding_model()
reranker = Choices.reranker_model()
Constraints
Constraints define valid parameter combinations. They prevent the optimizer from exploring invalid configurations.
Lambda Constraints
The simplest form -- pass lambda functions that return True for valid configs:
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
configuration_space={
"model": ["gpt-4o-mini", "gpt-4o"],
"temperature": [0.1, 0.5, 0.9],
"max_tokens": [256, 512, 1024],
},
constraints=[
lambda config: config["temperature"] < 0.8 if config["model"] == "gpt-4o" else True,
lambda config: config["max_tokens"] >= 512,
],
)
def my_function(query: str) -> str:
...
Lambda constraints can also receive metrics from past trials:
constraints=[
lambda config, metrics: metrics.get("cost", 0) <= 0.10,
]
Builder-Style Constraints
For typed parameters, use the builder methods on Range, IntRange, and Choices objects combined with the implies() function:
from traigent import Range, IntRange, Choices, implies
model = Choices(["gpt-4o-mini", "gpt-4o"])
temperature = Range(0.0, 1.0)
max_tokens = IntRange(100, 4096)
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
model=model,
temperature=temperature,
max_tokens=max_tokens,
constraints=[
implies(model.equals("gpt-4o"), temperature.lte(0.7)),
implies(model.equals("gpt-4o-mini"), max_tokens.gte(256)),
],
)
def my_function(query: str) -> str:
...
Three Syntax Styles for Constraints
All three produce equivalent Constraint objects:
from traigent import Range, Choices, implies, when
model = Choices(["gpt-4o-mini", "gpt-4o"])
temp = Range(0.0, 1.0)
implies(model.equals("gpt-4o"), temp.lte(0.7))
model.equals("gpt-4o") >> temp.lte(0.7)
when(model.equals("gpt-4o")).then(temp.lte(0.7))
Combining Conditions
Use & (and), | (or), ~ (not) operators to combine conditions:
from traigent import Range, Choices, implies
model = Choices(["gpt-4o-mini", "gpt-4o", "claude-3-5-sonnet-20241022"])
temp = Range(0.0, 1.5)
max_tokens = IntRange(100, 4096)
constraints = [
implies(
model.equals("gpt-4o") & temp.gte(0.8),
max_tokens.gte(1024),
),
implies(
~model.equals("gpt-4o-mini"),
temp.lte(1.0),
),
implies(
model.equals("gpt-4o") | model.equals("claude-3-5-sonnet-20241022"),
temp.lte(0.9),
),
]
Operator precedence warning: Python precedence is ~ > >> > & > |. Always use parentheses when combining &/| with >>:
(model.equals("gpt-4o") & temp.lte(0.7)) >> max_tokens.gte(1000)
model.equals("gpt-4o") & temp.lte(0.7) >> max_tokens.gte(1000)
See references/constraints.md for the full constraint system reference.
ConfigSpace Object
For complex setups, bundle parameters and constraints into a ConfigSpace:
from traigent import Range, IntRange, Choices, implies
from traigent.api.config_space import ConfigSpace
temperature = Range(0.0, 1.0, name="temperature", unit="ratio")
max_tokens = IntRange(100, 4096, name="max_tokens", unit="tokens")
model = Choices(["gpt-4o-mini", "gpt-4o"], name="model")
constraints = [
implies(model.equals("gpt-4o"), temperature.lte(0.7)),
]
space = ConfigSpace(
tvars={"temperature": temperature, "max_tokens": max_tokens, "model": model},
constraints=constraints,
description="QA optimization space",
)
result = space.validate({"temperature": 0.5, "max_tokens": 2000, "model": "gpt-4o"})
print(result.is_valid)
sat = space.check_satisfiability()
print(sat)
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
configuration_space=space,
)
def my_function(query: str) -> str:
config = traigent.get_config()
...
Common Patterns
Model Selection with Cost Awareness
from traigent import Range, Choices, implies
model = Choices(["gpt-4o-mini", "gpt-4o"])
temperature = Range(0.0, 1.0)
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy", "cost"],
model=model,
temperature=temperature,
constraints=[
implies(model.equals("gpt-4o"), temperature.lte(0.7)),
],
)
def answer(question: str) -> str:
config = traigent.get_config()
...
RAG Pipeline Tuning
from traigent import Range, IntRange, Choices
@traigent.optimize(
eval_dataset="rag_evals.jsonl",
objectives=["accuracy"],
model=Choices.model(provider="openai"),
temperature=Range.temperature(conservative=True),
k=IntRange.k_retrieval(),
chunk_size=IntRange.chunk_size(),
chunk_overlap=IntRange.chunk_overlap(),
retriever=Choices.retriever_type(),
)
def rag_query(question: str) -> str:
config = traigent.get_config()
...
Multi-Agent Parameters
Assign parameters to specific agents using the agent keyword:
from traigent import Range, Choices
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
planner_model=Choices(["gpt-4o-mini", "gpt-4o"], agent="planner"),
planner_temperature=Range(0.0, 0.5, agent="planner"),
executor_model=Choices(["gpt-4o-mini", "gpt-4o"], agent="executor"),
executor_temperature=Range(0.5, 1.0, agent="executor"),
)
def multi_agent_workflow(task: str) -> str:
config = traigent.get_config()
...
Temperature Tuning Only
The minimal configuration -- just optimize temperature:
import traigent
from traigent import Range
@traigent.optimize(
eval_dataset="evals.jsonl",
objectives=["accuracy"],
temperature=Range.temperature(),
)
def my_function(query: str) -> str:
config = traigent.get_config()
...
Next Steps
You have defined the search space. Now run it:
traigent-optimize-run — launch the optimization: algorithm choice (auto/grid/random/cloud-only smart), max_trials, cost limits, and the mandatory dry-run-first gate. This is the next lifecycle step (configuration-space → run-optimization → analyze-results).
traigent-setup-decorator — if you still need to wire evaluation/objectives/injection onto @traigent.optimize() before running.
See Also
traigent — lifecycle driver (dry-run-first / cost-approval mandate)
traigent-optimize-run — run the space you just defined
traigent-analyze-results — read best_config/best_score and the trade-off after the run
Traigent Interaction Policy
Track an interaction profile and adapt to it. Persona (stable): control=delegate|guided|inspect,
expertise=se|ds|unknown. Mood (this session): pace=execute|balanced|explore. Default when
unknown: guided,se,balanced. Infer from explicit user statements first, then recent behavior;
an explicit correction wins immediately. Never store or send this profile anywhere by default.
Fetch the live profile (when available)
At session or skill start, if a configured Traigent client is available, seed the profile from the
backend with the skill name:
policy = None
try: policy = await client.get_interaction_policy(skill="<this skill>")
except Exception: pass
Treat the returned profile as the STARTING seed: its control/expertise/pace axes plus
question_budget, options_max, and jargon_level replace the static defaults below. Explicit user
corrections in-conversation ALWAYS override the seed. If the call is unavailable or
fallback_policy="static_v1", simply use the static defaults below; the SDK already fails soft.
- Always be concise.
- Match terminology to expertise. For
se: plain engineering words; define each Traigent or
statistics term once in plain language (no Bayesian / variance-decomposition / Pareto jargon
unless asked). For ds: compact optimization and statistical terms are fine.
- Presenting options: show at most 3, mark exactly one Recommended, and give one short
persona-appropriate trade-off per option.
- Autonomy. For
delegate or execute: pick the recommended reversible action and proceed, asking
only at hard gates. For guided: offer options with a recommendation at the key decisions. For
inspect or explore: give brief rationale or evidence before asking, and ask before branch
choices.
- Hard gates — always confirm regardless of persona: paid or provider model calls, sending data or
private content off the machine, destructive edits, decisions the Traigent service is meant to
return, and any missing fact the step truly requires.
- Always end by recommending the next Traigent skill or action to take.
- Never weaken Traigent safety: dry-run before any paid run; get explicit approval before real cost
or before any data leaves the machine; treat service-returned plans and next steps as
authoritative. Never put the persona profile or any private content into telemetry, run metadata,
experiment names, logs, or provenance files.