Advanced Features

Multi-agent systems, LLM integration, observability, memory, and scheduling — Syntecnia's power features for production-grade agentic programs.

1. Multi-Agent Coordination

Syntecnia lets you define and spawn multiple independent agents that collaborate through a shared blackboard and signal-based messaging. Each agent runs in its own thread with its own interpreter; only the blackboard and signal queue cross boundaries.

agent Researcher
    require net("*.wikipedia.org")
    task search(query)
        let data be fetch(query)
        share data as "research"

agent Writer
    observe "research" as data
    let report be generate "report" given data

spawn Researcher with query = "AI safety"

Blackboard (shared state)

The blackboard is thread-safe shared state that agents write to with share and read from with observe. It is the only memory that crosses agent boundaries.

  • Each agent has its own interpreter and local variable scope.
  • Only named blackboard keys are visible across agents.
  • observe blocks until the named key is available.
When multiple worker agents share the same key concurrently, the last write wins. Coordinate writes explicitly or use unique keys per worker.

Signals (messaging)

Signals provide lightweight one-shot messaging between agents using a queue-based mechanism.

  • signal "done" — post a named signal, optionally with a value.
  • wait_for "done" as result — block until the signal arrives and bind its value.
  • Signals are queue-based: each posted signal is consumed by exactly one waiter.
If you post one signal but have N consumers waiting, only one consumer receives it. Use N separate signal calls — one per consumer — for fan-out delivery.

Resource Locks

Syntecnia performs preventive conflict detection on resources declared by agents. The runtime can identify potential write conflicts before they occur and surface them as diagnostics rather than silent data races.

Declare resource requirements with require at the top of an agent body. This enables both safety checks and the capability permission system.

Agent Lifecycle

Agents must be defined before they are spawned. The runtime tracks each agent through a well-defined state machine:

  • STARTING — agent thread is initialising.
  • WORKING — actively executing a task.
  • WAITING — blocked on observe or wait_for.
  • DONE — task completed successfully.
  • ERROR — an unhandled failure occurred.
Each agent runs in a real OS thread. Spawn only as many agents as your workload justifies; idle WAITING agents still hold a thread.

2. LLM Integration

Syntecnia treats language model calls as first-class expressions. The runtime manages prompt construction, provider routing, validation, and retries transparently.

let analysis be analyze sales_data for "trends"
let action   be decide between ["refund", "replace"] given complaint
let response be generate "email" given ticket with tone = "empathetic"

Providers

Select the backend model at launch time via the CLI flag:

anthropic openai ollama minimax mock
Provider Models Notes
anthropic Claude family Default for production
openai GPT family Requires OPENAI_API_KEY
ollama Any local model No network required; runs locally
minimax MiniMax models Requires MINIMAX_API_KEY
mock Deterministic stub for tests

Pass the flag at runtime: syntecnia run program.syn --provider anthropic

Response Validation

The decide expression enforces that the LLM returns exactly one of the provided options. The runtime automatically retries with corrective feedback on invalid responses.

  • decide accepts only values from the supplied list — any other output triggers a retry.
  • Up to 3 retries are attempted; each retry sends the LLM its prior invalid response along with an explanation of the constraint.
  • On each call, the LLM receives full program context: intent, current variables, active rules, memory, and execution progress.
Use decide over raw generate wherever you need a constrained choice. The validation loop is automatic and surfaces errors clearly if all retries fail.

3. Human Interaction

Syntecnia provides built-in primitives for pausing execution and requesting human input or approval at critical decision points.

approve "Deploy to production?"
let choice be ask "Which environment?" with ["staging", "prod"]
confirm "Send email to 500 customers?"
show preview as "Email Preview"
  • approve — presents a yes/no gate; execution halts until a human confirms or rejects.
  • ask — prompts for a selection from a list of options and binds the result.
  • confirm — similar to approve, used for explicit acknowledgement of consequential actions.
  • show … as — renders a value for human review with a labelled title, without requiring a response.
In non-interactive mode (e.g., CI pipelines), all approve and confirm calls are auto-approved and ask selects the first option. Pass the appropriate flag to opt in.
The interaction handler is pluggable. You can swap the default terminal handler for a queue-based or webhook callback handler to integrate human-in-the-loop workflows into external systems.

4. Observability

Syntecnia has structured tracing, measurement, and checkpointing built into the language. No external instrumentation library is required.

trace "payment_processing"
    log "Processing order " + order_id
    measure "db_query"
        let result be query(sql)
    checkpoint "after_query"
  • trace — opens a named span. All nested operations are attributed to this span in the output.
  • log — emits a structured log line with timestamp and active span context.
  • measure — wraps a block and records its wall-clock duration as a named metric.
  • checkpoint — marks a named point in execution, usable for progress recovery and debugging.

Rich Error Diagnostics

When a runtime error occurs, Syntecnia surfaces a structured diagnostic that includes everything needed to understand and fix the failure:

  • Location — file, line, and column of the failing expression.
  • Source line — the exact Syntecnia source text that failed.
  • Intent — the high-level goal the agent was pursuing at the time of failure.
  • Variables at failure — a snapshot of all in-scope variable bindings.
  • Suggestions — concrete, contextual hints for resolution.
  • Error category and recoverability — whether the error is transient, permanent, or requires human escalation.

Automatic Recovery

Syntecnia's runtime attempts recovery before surfacing an error to the program. The recovery strategies are applied in order:

  1. Retry with backoff — transient failures (network, rate limits) are retried with exponential backoff.
  2. Fallback to cached or default data — if a fetch fails and cached data exists, it is used transparently.
  3. Partial results — when a collection operation partially succeeds, the successful subset is returned with a warning.
  4. Speculative alternatives — the runtime may attempt a semantically equivalent alternative path.
  5. Human escalation — if all automated recovery strategies fail, execution pauses and the human interaction handler is invoked.
Wrap I/O operations in try/recover blocks to define custom recovery logic. Relying solely on automatic recovery means unhandled permanent failures will escalate to the human handler or terminate the agent.

5. Agent Memory System

Beyond the blackboard, Syntecnia provides a durable memory layer that persists across agent restarts and program runs. It covers progress tracking, semantic memory, and business rule enforcement.

Progress Tracking

Progress tracking lets a multi-step task survive crashes and resume from the last completed step rather than starting over.

create_progress("sync", ["fetch", "validate", "update"])
start_step("sync", "fetch")
complete_step("sync", "fetch", "100 items")
  • create_progress(id, steps) — registers a named task with an ordered list of step names.
  • start_step(id, step) — marks a step as in-progress.
  • complete_step(id, step, result) — marks a step done and stores its output.
  • resume_point(id) — returns the name of the next incomplete step; use this at startup to skip already-completed work after a crash.
resume_point returns the first step whose status is not complete. If all steps are complete it returns null, signalling that the task is finished.

Persistent Memory

Agents can store and retrieve semantic memories organised by category. Memory persists across runs and is surfaced to LLM calls as context.

remember("preference", "Customer prefers formal tone", ["communication"])
let prefs be recall("preference", ["communication"])
forget_memory(entry_id)
  • remember(category, text, tags) — stores a memory entry with a category and optional tags for retrieval filtering.
  • recall(category, tags) — retrieves matching memory entries; tags narrow the search.
  • forget_memory(entry_id) — permanently removes a specific memory entry by its ID.

Valid categories (must be written in English):

preference rule learning decision context
Category names must be in English regardless of the application's locale. Using localised category strings will prevent correct retrieval and rule matching.

Owner Rules

Owner rules let the operator or application embed hard constraints and soft preferences that are evaluated against agent decisions at runtime.

add_rule("max_discount", "must", "discount <= 0.20", "pricing")
let violations be check_rules("pricing", {discount: 0.25})
  • add_rule(name, level, expression, category) — registers a named rule with an enforcement level and a logical expression.
  • check_rules(category, context) — evaluates all rules in a category against the provided context object and returns any violations.

Enforcement levels:

LevelBehaviour
mustHard block — a violation raises an error and halts execution.
shouldWarning — a violation is logged but execution continues.
avoidPreference against — surfaces as a low-priority advisory.
preferPreference for — guides LLM generation toward the desired outcome.

6. Cron / Scheduling

Syntecnia includes a lightweight in-process scheduler for running tasks on a delay or recurring interval — no external cron daemon required.

cron_every(60, my_task)
cron_after(300, cleanup)
cron_cancel("my_task")
  • cron_every(seconds, task) — schedules task to run repeatedly every seconds seconds. The first run occurs after one full interval.
  • cron_after(seconds, task) — schedules task to run once after a delay of seconds seconds.
  • cron_cancel(name) — cancels a scheduled task by its name, preventing any future executions.
The scheduler runs inside the Syntecnia runtime process. If the process exits, all pending scheduled tasks are lost. For durable scheduling across restarts, combine cron_every with progress tracking so tasks can self-resume.

7. Common Anti-Patterns

Avoid these patterns to keep agents reliable, safe, and correct.

No try/recover around I/O

An agent without error handling will die on the first I/O failure — network timeout, disk error, API rate limit. Wrap all I/O in try/recover blocks and define explicit fallback behaviour.

Relying on intent to restrict actions

Intent descriptions are guidance for the LLM, not security boundaries. Use require declarations to define hard capability constraints. An agent without explicit require net(...) should not be able to make network calls regardless of its stated intent.

One signal for N consumers

A single signal "done" is consumed by exactly one waiting agent. If N agents are waiting on the same signal name, only one will unblock. Post N signals — one per consumer — for broadcast delivery.

Sharing from N workers with a common key

When multiple agents share data under the same blackboard key, the last write wins and earlier values are silently overwritten. Use unique per-agent keys (e.g., "result_" + agent_id) and aggregate them in a coordinator agent.

Not using parameterized SQL

Constructing SQL by concatenating user-controlled strings is an injection risk even inside an agent. Always pass parameters separately through the query API rather than building raw SQL strings.