Skip to content

Nexa Language Reference Manual

This manual details the syntax specification, semantic rules, and type system of the Nexa language. All grammar rules strictly match the source code in src/nexa_parser.py.


📖 About This Manual

This reference manual is organized according to the following principles:

  • Precision: Every syntactic construct has a clear semantic definition
  • Completeness: Covers all language features, including v1.1–v1.3.x additions
  • Practicality: Provides sufficient examples for understanding

Reading Advice

If you're new to Nexa, we recommend reading Quickstart and Basic Syntax first, then returning to this manual.


1. Lexical Structure

1.1 Identifiers

Nexa identifiers follow these rules:

identifier ::= [a-zA-Z_][a-zA-Z0-9_]*

Valid identifier examples:

MyAgent           // PascalCase (recommended for Agents)
my_tool          // snake_case (recommended for tools)
_process_data    // underscore prefix
Parser2          // contains digits (cannot start)

Invalid identifier examples:

2ndAgent         // starts with digit
my-agent         // contains hyphen
agent.name       // contains dot

1.2 Keywords

Nexa reserves the following keywords that cannot be used as identifiers:

Category Keywords
Declarations agent, tool, protocol, flow, test, type, struct, enum, trait, impl, fn, job, server, db, auth, kv
Control Flow match, intent, loop, until, if, else, for, while, break, continue
Semantic Control semantic_if, fast_match, against
Exception Handling try, catch
Error Propagation ?, otherwise
Type Constraints implements, uses
Design by Contract requires, ensures, invariant
Concurrency spawn, parallel, race, channel, after, schedule, select
Deferred Execution defer
Pipe |>
Null Coalescing ??
String Interpolation #{expr}
Template template
Other print, assert, fallback, join, role, model, prompt, memory, stream, cache, experience, include

1.3 Literals

String Literals

"Hello, World!"           // Regular string
"Line 1\nLine 2"         // With escape characters
"Quote: \"nested\""      // With quotes
"""Multi-line string"""   // Multi-line string

String Interpolation Literals (v1.3.x)

"Hello #{name}, you are #{age} years old!"   // Ruby-style interpolation
"Status: #{result ?? 'pending'}"             // Interpolation + null coalescing
"Agent #{agent.name} responding"             // Interpolation + dot access

Interpolation expression support:

Expression Type Example Python Translation
Simple identifier #{name} name
Dot access #{user.name} user["name"]
Bracket access #{arr[0]} arr[0]
Combined #{data.items[0].name} data["items"][0]["name"]

Escape: \#{ → literal #{

Template String Literals (v1.3.6)

template"""Hello {{name | upper}}!"""
template"""{{#for item in items}}{{@index}}:{{item}}{{/for}}"""
template"""{{#if is_admin}}Admin{{#elif is_mod}}Mod{{#else}}User{{/if}}"""
template"""{{> card user_data}}"""

Regular Expression Literals

r"\d{4}-\d{2}-\d{2}"     // Date format
r"^[a-zA-Z_]\w*$"        // Identifier pattern
r"https?://[^\s]+"      // URL pattern

Number Literals

42              // Integer
3.14            // Float
2048            // For max_tokens etc.

1.4 Comments

// Single-line comment

/*
 * Multi-line comment
 * Can span multiple lines
 */

/// Document comment (for Agent, Tool descriptions)

2. Declarations

2.1 Agent Declaration

agent_decl ::= agent_decorator* "agent" IDENTIFIER 
               ["->" return_type]
               ["uses" use_identifier_list]
               ["implements" IDENTIFIER]
               requires_clause*
               ensures_clause*
               "{" agent_property* "}"

Examples:

// Basic definition
agent Greeter {
    role: "Friendly greeting assistant",
    model: "deepseek/deepseek-chat",
    prompt: "You are a warm and friendly assistant."
}

// With decorators
@limit(max_tokens=600)
@timeout(seconds=30)
agent Coder {
    prompt: "Write a short Python implementation.",
    model: "minimax/minimax-m2.5"
}

// With contract clauses
agent Reviewer implements ReviewResult
    requires: "input contains code"
    ensures: "result includes score"
{
    prompt: "Review the provided code.",
    model: "deepseek/deepseek-chat"
}

// With return type
agent Analyzer -> ReportResult uses std.http {
    role: "Data Analyst",
    prompt: "Analyze data and generate reports"
}

Agent Properties:

Property Type Required Description
role string No Agent role description
prompt string Yes Agent core task instruction
model string No LLM model (format: provider/model)
memory string No Memory mode
stream boolean No Streaming output
cache boolean No Smart caching
experience string No Long-term memory file
fallback string/list No Fallback model
uses identifier_list No Stdlib permissions
implements identifier No Protocol constraint

Agent Decorators:

Decorator Parameters Description
@limit max_tokens=INT Max output tokens
@timeout seconds=INT Execution timeout
@retry count=INT Failure retry count
@temperature value=FLOAT Model temperature

2.2 Tool Declaration

tool_decl ::= "tool" IDENTIFIER "{" tool_body "}"
tool_body ::= tool_body_standard | tool_body_mcp | tool_body_python

Examples:

// Standard tool
tool web_search {
    description: "Search web content",
    parameters: {
        "query": "Search keyword",
        "limit": "Result count limit"
    }
}

// MCP tool
tool search_mcp {
    mcp: "web-search-mcp-server"
}

// Python tool
tool calculator {
    python: "import math; return math.sqrt(input)"
}

2.3 Protocol Declaration

protocol_decl ::= "protocol" IDENTIFIER "{" protocol_body* "}"
protocol_body ::= IDENTIFIER ":" STRING_LITERAL ","?
                | IDENTIFIER ":" type_expr ","?

Examples:

// String type annotation (legacy format)
protocol ReviewResult {
    score: "int",
    summary: "string",
    bug_list: "list[string]",
    is_critical: "boolean"
}

// Type expression annotation (v1.3.1+)
protocol UserProfile {
    name: String,
    age: Int,
    email: Option[String]
}

2.4 Flow Declaration

flow_decl ::= "flow" IDENTIFIER ["(" param_list ")"] ["->" type_expr]
              requires_clause* ensures_clause* block

Examples:

// Basic definition
flow main {
    result = Greeter.run("Hello!");
    print(result);
}

// With parameters and return type
flow analyze(data: String) -> ReportResult
    requires: data != None
    ensures: "result contains analysis"
{
    return Analyzer.run(data);
}

2.5 Test Declaration

test_decl ::= "test" STRING_LITERAL block

Example:

test "Translation test" {
    result = Translator.run("Hello, World!");
    assert "Contains Chinese translation" against result;
}

2.6 Type Declaration (Semantic Types)

type_decl ::= "type" IDENTIFIER "=" semantic_type
semantic_type ::= base_type "@" STRING_LITERAL    // Constrained type
               | base_type                          // Simple type

Examples:

type Email = str @ "valid email address format"
type PositiveInt = int @ "must be greater than 0"
type Score = float @ "between 0.0 and 100.0"

2.7 Struct Declaration (v1.3.x)

struct_decl ::= "struct" IDENTIFIER "{" struct_field* "}"
struct_field ::= IDENTIFIER ":" type_expr ","?

Examples:

struct Point { x: Int, y: Int }
struct AgentResult { answer: String, confidence: Float, tokens: Int }
struct UserProfile { name: String, email: String, age: Int }

Runtime representation (handle-as-dict):

{"_nexa_struct": "Point", "_nexa_struct_id": 1, "x": 1, "y": 2}

2.8 Enum Declaration (v1.3.x)

enum_decl ::= "enum" IDENTIFIER "{" enum_variant* "}"
enum_variant ::= IDENTIFIER "(" IDENTIFIER ")"    // Value variant
              | IDENTIFIER                          // Unit variant

Examples:

enum Option { Some(value), None }
enum Result { Ok(value), Err(error) }
enum AgentState { Idle, Running, Error(message) }

Runtime representation (handle-as-dict):

// Value variant
{"_nexa_variant": "Some", "_nexa_enum": "Option", "_nexa_variant_id": 1, "value": 42}
// Unit variant
{"_nexa_variant": "None", "_nexa_enum": "Option"}

2.9 Trait Declaration (v1.3.x)

trait_decl ::= "trait" IDENTIFIER "{" trait_method* "}"
trait_method ::= "fn" IDENTIFIER "(" param_list ")" ["->" type_expr]

Examples:

trait Printable { fn format() -> String }
trait Comparable { fn compare(other: Self) -> Int }
trait Serializable { fn serialize() -> String }

2.10 Impl Declaration (v1.3.x)

impl_decl ::= "impl" IDENTIFIER "for" IDENTIFIER "{" impl_method* "}"
impl_method ::= "fn" IDENTIFIER "(" param_list ")" ["->" type_expr] block

Example:

impl Printable for Point {
    fn format() -> String {
        return "Point(x=#{self.x}, y=#{self.y})"
    }
}

2.11 Job Declaration (v1.3.3)

job_decl ::= "job" IDENTIFIER "on" STRING_LITERAL 
             ["(" job_options ")"] "{" job_body "}"

Example:

job SendEmail on "emails" (retry: 2, timeout: 120) {
    perform(user_id) {
        // Send email logic
    }
    on_failure(error, attempt) {
        // Failure handling logic
    }
}

Job Options:

Option Type Description
retry int Retry count
timeout int Timeout in seconds

2.12 Server Declaration (v1.3.4)

server_decl ::= "server" INT "{" server_body "}"

Example:

server 8080 {
    static "/assets" from "./public"
    cors { origins: ["*"], methods: ["GET", "POST"] }
    middleware [auth_middleware]
    require_auth "/admin"

    route GET "/chat" => ChatBot
    route POST "/analyze" => DataExtractor |>> Analyzer
    semantic route "/help" => HelpBot

    group "/admin" {
        middleware [require_admin]
        route GET "/" => AdminBot
    }
}

Server Directives:

Directive Description
static Static file serving
cors CORS configuration
middleware Middleware list
require_auth Auth-required path
route Standard route
semantic route Semantic route
group Path grouping

HTTP Methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS

Route Handlers:

// Single handler
route GET "/chat" => ChatBot

// DAG chain handler
route POST "/analyze" => DataExtractor |>> Analyzer |>> Reporter

2.13 DB Declaration (v1.3.5)

db_decl ::= "db" IDENTIFIER "=" "connect" "(" STRING_LITERAL ")"

Examples:

db app_db = connect("sqlite://data.db")
db prod_db = connect("postgresql://user:pass@localhost/mydb")

2.14 Auth Declaration (v1.3.6)

auth_decl ::= "auth" IDENTIFIER "=" "enable_auth" "(" STRING_LITERAL ")"

Example:

auth myAuth = enable_auth('{"providers": ["google", "github"]}')

2.15 KV Declaration (v1.3.6)

kv_decl ::= "kv" IDENTIFIER "=" "open" "(" STRING_LITERAL ")"

Example:

kv myCache = open("sqlite://cache.db")

3. Expressions

3.1 Pipe Operator |> (v1.3.x)

Left-to-right data flow pipe, LHS becomes the first argument of the RHS function.

x |> f          // Equivalent to f(x)
x |> f(a, b)    // Equivalent to f(x, a, b)
data |> std.text.upper
prompt |> agent.run |> extract_answer

Difference from >>

|> is a function pipe (left value passed as first argument), >> is an Agent pipeline (left value passed as input to next Agent).


3.2 Agent Pipeline Operator >>

Agent pipeline data transfer.

A >> B              // B.run(A.run(input))
A >> B >> C         // C.run(B.run(A.run(input)))
input >> A >> B     // Starting from input

3.3 DAG Operators |>> and &>>

// |>> Fan-out: input sent to multiple Agents simultaneously
input |>> [AgentA, AgentB, AgentC]

// &>> Merge: collect multiple results then pass to next Agent
[results] &>> Summarizer

// Combined usage
"topic" |>> [Writer, Reviewer, Editor] &>> Publisher

3.4 Null Coalescing Operator ?? (v1.3.x)

expr ?? fallback    // If expr is None/Option::None/empty dict, return fallback
result ?? "fallback"
config.timeout ?? 30
agent.run(prompt) ?? "I couldn't process that"

Semantics:

Left Value Result
None Right value
Option::None dict Right value
Empty dict {} Right value
Any other value Left value

3.5 Error Propagation Operator ? (v1.3.2)

Rust-style error propagation, propagates errors upward on failure.

let value = parse(input) ?           // If parse returns error, propagate error
let result = risky_operation() ?     // Same

3.6 Otherwise Operator (v1.3.2)

Provides error fallback value.

let result = risky_op() otherwise "fallback"   // If error, return "fallback"

3.7 Match Expression (v1.3.x)

match_expr ::= "match" expression "{" match_arm* "}"
match_arm ::= pattern "=>" expression

7 Pattern Types:

Pattern Syntax Description
Wildcard _ Matches anything, no binding
Variable name Matches anything, binds variable
Literal 42, "hello", true Matches exact value
Tuple (a, b) Matches tuple/array
Array [a, b, ..rest] Matches array + rest collector
Map { name, age: a, ..other } Matches dict + rest collector
Variant Option::Some(v) Matches enum variant

Examples:

// Basic matching
match result {
    Option::Some(answer) => answer
    Option::None => "no response"
}

// Literal matching
match status {
    200 => "success"
    404 => "not found"
    _ => "unknown"
}

// Destructuring match
match entry {
    (key, value) => "#{key}: #{value}"
}

// Array destructuring
match items {
    [first, second, ..rest] => "first=#{first}, rest=#{rest.length}"
}

// Map destructuring
match user {
    { name, age: a, ..other } => "#{name} is #{a} years old"
}

3.8 Let Destructuring (v1.3.x)

let_pattern_stmt ::= "let" pattern "=" expression

Examples:

let (key, value) = entry
let [first, ..rest] = items
let { name, age: a } = user_data

3.9 For Destructuring (v1.3.x)

for_pattern_stmt ::= "for" pattern "in" expression block

Example:

for (name, score) in rankings {
    print("#{name}: #{score}")
}

3.10 Variant Call Expression (v1.3.x)

variant_call_expr ::= IDENTIFIER "::" IDENTIFIER ["(" expression ")"]

Examples:

let opt = Option::Some(42)
let res = Result::Ok("success")
let state = AgentState::Running
let err = AgentState::Error("connection failed")

3.11 Field Init Expression (v1.3.x)

field_init ::= IDENTIFIER ":" expression

Examples:

let p = Point(x: 1, y: 2)
let result = AgentResult(answer: "yes", confidence: 0.95, tokens: 150)

3.12 Concurrency Expressions (v1.3.6)

spawn_expr ::= "spawn" "(" expression ")"
parallel_expr ::= "parallel" "(" expression ")"
race_expr ::= "race" "(" expression ")"
channel_expr ::= "channel" "(" ")"
after_expr ::= "after" "(" expression "," expression ")"
schedule_expr ::= "schedule" "(" expression "," expression ")"
select_expr ::= "select" "(" expression ["," expression] ")"

Examples:

spawn(my_task)
parallel([task_a, task_b, task_c])
race([fast_task, slow_task])
channel()
after(500ms, cleanup())
schedule(every 30s, health_check())

4. Statements

4.1 Defer Statement (v1.3.x)

defer_stmt ::= "defer" expression ";"

Executes in LIFO order, even if errors occur (similar to Go defer).

Examples:

defer cleanup(db)
defer log("operation complete")
defer agent_cleanup(agent)

4.2 Contract Clauses (v1.2.0)

requires_clause ::= "requires" STRING_LITERAL        // Semantic precondition
                  | "requires" comparison_expr        // Deterministic precondition

ensures_clause ::= "ensures" STRING_LITERAL           // Semantic postcondition
                | "ensures" comparison_expr           // Deterministic postcondition

Examples:

// Deterministic contract
flow transfer(amount: int) -> Result
    requires: amount > 0
    ensures: result.success == true
{
    // Transfer logic
}

// Semantic contract (evaluated by LLM at runtime)
flow review(code: string) -> Report
    requires: "input contains valid source code"
    ensures: "result includes actionable feedback"
{
    // Review logic
}

4.3 Traditional Control Flow (v1.0.1+)

// if/else if/else
if condition {
    // ...
} else if other_condition {
    // ...
} else {
    // ...
}

// for each loop
for each item in collection {
    // ...
}

// while loop
while condition {
    // ...
}

// break/continue
for each item in items {
    if item == "skip" { continue; }
    if item == "stop" { break; }
}

4.4 Semantic Control Flow

// loop until — natural language loop termination control
loop {
    draft = Writer.run(feedback);
    feedback = Critic.run(draft);
} until ("Article quality is excellent")

// semantic_if — semantic condition judgment
semantic_if "user is frustrated" {
    SupportBot.run("Provide comfort and help");
}

// fast_match — fast intent matching
result = fast_match user_input {
    intent("Check weather") => WeatherBot.run(user_input),
    intent("Check news") => NewsBot.run(user_input),
    _ => ChatBot.run(user_input)
}

4.5 Python Escape Hatch (v1.0.1+)

stats = python! """
    import statistics
    data = json.loads(raw_data)
    return statistics.mean(data)
"""

5. Type System (v1.3.1)

5.1 Type Expressions

type_expr ::= type_union_expr | type_non_union_expr

type_union_expr ::= type_non_union_expr ("|" type_non_union_expr)+
type_non_union_expr ::= type_compound_expr "?" | type_compound_expr

type_compound_expr ::= "str" | "int" | "float" | "bool" | "unit"
                    | "Option" "[" type_expr "]"
                    | "Result" "[" type_expr "," type_expr "]"
                    | "list" "[" type_expr "]"
                    | "dict" "[" type_expr "," type_expr "]"
                    | IDENTIFIER    // Type alias

Type Examples:

Type Description Example Value
Int Integer 42
String / str String "hello"
Float / float Float 3.14
Bool / bool Boolean true
Unit / unit Unit type ()
Option[T] Optional type Some(42) / None
Result[T, E] Result type Ok("success") / Err("error")
list[T] List [1, 2, 3]
dict[K, V] Dictionary {"key": "value"}
T | U Union type Int | String
T? Optional shorthand Equivalent to Option[T]

5.2 Type Checking Modes

Mode Environment Variable Description
strict NEXA_TYPE_MODE=strict Type mismatch = runtime error
warn NEXA_TYPE_MODE=warn Type mismatch = log warning (default)
forgiving NEXA_TYPE_MODE=forgiving Type mismatch = silently ignore

Priority: CLI flag > Environment variable > nexa.toml > Default (warn)

5.3 Lint Modes

Mode Environment Variable Description
default NEXA_LINT_MODE=default Only check code with type annotations (default)
warn NEXA_LINT_MODE=warn Warn about missing type annotations
strict NEXA_LINT_MODE=strict Missing type annotations = lint error

6. Error Handling

6.1 Error Types

Error Type Description Trigger Scenario
ContractViolation Contract violation requires/ensures/invariant condition not satisfied
TypeViolation Type violation Type mismatch in strict mode
TypeWarning Type warning Type mismatch in warn mode
ValidationError Validation error Semantic validation failure
NexaResult.Err Result error Error branch of Result[T, E] type
NexaOption.None Null value Null value of Option[T] type

6.2 Error Propagation

// ? operator: propagate error
let value = parse(input) ?

// otherwise operator: provide fallback
let result = risky_op() otherwise "fallback"

// try/catch
try {
    result = risky_operation();
} catch (error) {
    print("Error: #{error}");
}

7. Runtime Architecture Patterns

7.1 Handle-as-dict Pattern

All runtime handles (DB connections, KV stores, Auth sessions, compiled templates, struct instances, enum variants) are plain Python dicts with _nexa_* prefixed keys for JSON compatibility.

7.2 Thread-safe Registry Pattern

All runtime modules use global registries with _registry_lock (threading.Lock) + _id_counter.

7.3 StdTool Namespace Pattern

Standard library tools are registered via StdTool into namespaces: std.db, std.auth, std.kv, std.concurrent, std.template, std.match, std.struct, std.enum, std.trait, etc.

7.4 BOILERPLATE Code Generation Pattern

Each feature adds imports and helper functions to the CodeGenerator's BOILERPLATE section.


快来问问agent吧!

Nexa Agent

Nexa 文档助手

我是Nexa文档AI助手,可以问我有关文档的一切!

由AI Hub提供支持