Intent System

How AI agents declare goals with intent blocks and the compiler generates verified implementations

Intent System

The intent system is Kōdo’s most distinctive feature. Instead of writing boilerplate code for common infrastructure patterns, AI agents declare what should happen using intent blocks. The compiler’s resolver maps those declarations to concrete implementations, then verifies the generated code satisfies all contracts and type constraints.

Why Intents?

Traditional programming requires agents to generate exact implementation details: connection pools, error handling, protocol negotiation, routing tables, and more. This creates surface area for bugs and forces agents to reason about low-level concerns that are repetitive and error-prone.

With intents, agents express goals. The compiler handles the rest.

// Instead of 50 lines of HTTP server setup...
intent http_server {
    port: 8080
    routes: [["GET", "/health", "handle_health"]]
}

The intent resolver generates all the necessary boilerplate — server initialization, route dispatch, error handling — and then runs the generated code through the full type checker and contract verifier. If anything is wrong, you get a compiler error, not a runtime crash.

Basic Syntax

An intent block lives inside a module and declares a resolver name followed by configuration keys:

module my_app {
    meta {
        purpose: "A simple console application",
        version: "1.0.0"
    }

    intent console_app {
        greeting: "Hello from intent-driven Kodo!"
    }
}

Compile and run:

cargo run -p kodoc -- build intent_demo.ko -o intent_demo
./intent_demo

Output: Hello from intent-driven Kodo!

The console_app resolver generates a main function that prints the greeting message. You wrote one line of configuration; the compiler wrote the rest.

How Resolution Works

The intent resolution pipeline has five stages:

  1. Parse — The parser produces an IntentDecl AST node containing the resolver name and configuration.
  2. Lookup — The resolver searches for a matching ResolverStrategy by name.
  3. Generate — The strategy reads the configuration and generates concrete Function AST nodes.
  4. Verify — The generated code is type-checked and contract-verified, just like hand-written code.
  5. Compile — If verification passes, the generated code enters the normal compilation pipeline.

This means intents are not macros or templates — they produce real, verified code that goes through every compiler phase. If the resolver generates code that violates a contract or has a type error, you get a proper compiler error pointing back to the intent block.

You can inspect what an intent resolves to:

kodoc intent-explain my_app.ko

This shows the concrete functions generated by each intent, making the resolution fully transparent and auditable.

Built-in Intent Resolvers

console_app — Console Application

The simplest resolver. Generates a main function that prints a greeting message.

module greeter {
    meta {
        purpose: "Console greeter",
        version: "1.0.0"
    }

    intent console_app {
        greeting: "Welcome to Kodo!"
        entry_point: "start"
    }

    fn start() {
        println("Application started")
    }
}
Config KeyTypeDescription
greetingStringMessage printed at startup
entry_pointStringFunction to call after greeting (optional)

math_module — Mathematical Functions

Declares a set of mathematical helper functions. The resolver registers them as a cohesive module with documentation.

module math_helpers {
    meta {
        purpose: "Math utility module",
        version: "1.0.0"
    }

    intent math_module {
        functions: [add, sub, mul, safe_div]
    }

    fn add(a: Int, b: Int) -> Int {
        return a + b
    }

    fn sub(a: Int, b: Int) -> Int {
        return a - b
    }

    fn mul(a: Int, b: Int) -> Int {
        return a * b
    }

    fn safe_div(a: Int, b: Int) -> Int {
        if b == 0 {
            return 0
        }
        return a / b
    }

    fn kodo_main() {
        let result: Int = add(10, mul(3, 4))
        print_int(result)
    }
}
Config KeyTypeDescription
functionsListList of function identifiers to include

http_server — HTTP Server

Generates a fully functional HTTP server with route dispatch. You define handler functions; the intent wires them to routes.

module web_service {
    meta {
        purpose: "HTTP server with route dispatch",
        version: "1.0.0"
    }

    fn handle_health() -> String {
        return "OK"
    }

    fn handle_echo() -> String {
        return "echo"
    }

    intent http_server {
        port: 9090
        routes: [
            ["GET", "/health", "handle_health"],
            ["POST", "/echo", "handle_echo"]
        ]
    }
}

The resolver generates a main function that starts a TCP listener, parses HTTP requests, and dispatches to the correct handler based on method and path. Unmatched routes return a 404 response.

Config KeyTypeDescription
portIntPort to listen on
routesListList of [method, path, handler_name] triples
not_foundStringCustom 404 handler function name (optional)

json_api — JSON REST API

Generates scaffolding for a JSON-based REST API with model and route declarations.

module api_service {
    meta {
        purpose: "JSON REST API",
        version: "1.0.0"
    }

    intent json_api {
        routes: ["/users", "/posts"],
        models: ["User", "Post"]
    }

    fn main() -> Int {
        println("API service started")
        return 0
    }
}
Config KeyTypeDescription
routesListAPI route paths
modelsListModel names for serialization
portIntServer port (optional)
base_pathStringAPI base path prefix (optional)
endpointsListEndpoint definitions (optional)

database — Database Connection

Generates connection setup and query stubs for database access.

module data_layer {
    meta {
        purpose: "Database access layer",
        version: "1.0.0"
    }

    intent database {
        driver: "sqlite",
        tables: ["users", "posts"],
        queries: [find_user, list_posts]
    }

    fn main() -> Int {
        println("Database layer initialized")
        return 0
    }
}
Config KeyTypeDescription
driverStringDatabase driver ("sqlite", "postgres", etc.)
tablesListTable names to generate access stubs for
queriesListQuery function identifiers

cache — In-Memory Cache

Generates caching infrastructure with configurable eviction strategy.

module caching {
    meta {
        purpose: "Cache layer with LRU eviction",
        version: "1.0.0"
    }

    intent cache {
        strategy: "lru",
        max_size: 1000
    }

    fn main() -> Int {
        println("Cache initialized")
        return 0
    }
}

The resolver generates cache_get, cache_set, and cache_invalidate functions.

Config KeyTypeDescription
strategyStringEviction strategy ("lru", "fifo", etc.)
max_sizeIntMaximum number of entries

queue — Message Queue

Generates producer/consumer infrastructure for message-based communication.

module messaging {
    meta {
        purpose: "Message queue with topics",
        version: "1.0.0"
    }

    intent queue {
        backend: "memory",
        topics: ["events", "tasks"]
    }

    fn main() -> Int {
        println("Queue service started")
        return 0
    }
}
Config KeyTypeDescription
backendStringQueue backend ("memory", "redis", etc.)
topicsListTopic names to create

cli — Command-Line Tool

Generates a CLI application with command dispatch, help text, and argument parsing.

module mytool {
    meta {
        purpose: "CLI tool with commands",
        version: "1.0.0"
    }

    fn do_greet() -> Int {
        println("Hello from CLI!")
        return 0
    }

    fn do_version() -> Int {
        println("mytool v1.0.0")
        return 0
    }

    intent cli {
        name: "mytool"
        version: "1.0.0"
        commands: [
            ["greet", "do_greet", "Print a greeting"],
            ["version", "do_version", "Show version"]
        ]
    }
}

The resolver generates a main function that reads command-line arguments and dispatches to the correct handler. Running with no arguments or an unknown command prints help text.

Config KeyTypeDescription
nameStringTool name (used in help output)
versionStringTool version
commandsListList of [name, handler_fn, description] triples

file_processor — File Processing Pipeline

Generates a pipeline that reads input, applies a transform function, and writes output.

module processor {
    meta {
        purpose: "File processing pipeline",
        version: "1.0.0"
    }

    fn transform(input: String) -> String {
        return input
    }

    intent file_processor {
        input: "stdin"
        output: "stdout"
        transform: transform
    }
}
Config KeyTypeDescription
inputStringInput source ("stdin" or a file path)
outputStringOutput destination ("stdout" or a file path)
transformIdentifierTransform function to apply to each line

worker — Worker Loop

Generates a worker loop that repeatedly executes a task function with configurable iteration limits and error handling.

module background_worker {
    meta {
        purpose: "Background worker with error handling",
        version: "1.0.0"
    }

    fn do_work() -> Int {
        println("Working...")
        return 0
    }

    fn handle_error() -> Int {
        println("Error occurred, recovering...")
        return 0
    }

    intent worker {
        task: do_work
        max_iterations: 5
        on_error: handle_error
    }
}

The resolver generates a main function containing a loop that calls the task function up to max_iterations times. If the task returns a non-zero value, the on_error handler is invoked.

Config KeyTypeDescription
taskIdentifierFunction to execute on each iteration
max_iterationsIntMaximum loop iterations
on_errorIdentifierError handler function

Composing Multiple Intents

A single module can contain multiple intent blocks. The resolver processes each one independently, and all generated code is merged before verification:

module composed_app {
    meta {
        purpose: "Composed intents demo",
        version: "1.0.0"
    }

    intent console_app {
        greeting: "Welcome to Kodo math!"
        entry_point: "greet"
    }

    intent math_module {
        functions: [add, mul]
    }

    fn greet() {
        print_int(0)
    }

    fn add(a: Int, b: Int) -> Int {
        return a + b
    }

    fn mul(a: Int, b: Int) -> Int {
        return a * b
    }

    fn kodo_main() {
        greet()
        let result: Int = add(3, mul(4, 5))
        print_int(result)
    }
}

This pattern lets agents compose infrastructure declaratively — combine a cache, a database, and an HTTP server in a single module, and the compiler wires everything together.

Agent Traceability with Intents

Intents integrate naturally with Kodo’s agent traceability system. An AI agent can declare an intent with confidence and authorship annotations:

@authored_by(agent: "claude")
@confidence(0.92)
fn handle_request() -> String {
    return "processed"
}

intent http_server {
    port: 8080
    routes: [["GET", "/process", "handle_request"]]
}

The compilation certificate (.ko.cert.json) records:

  • Which intents were resolved and what code was generated
  • The confidence scores of handler functions referenced by intents
  • Whether all contracts on generated code were verified

This creates a full audit trail: you can trace from a running endpoint back to the AI agent that wrote the handler, see its confidence score, and verify that all contracts passed.

Custom Resolvers (Planned)

:::note[Future Feature] Custom resolvers are a planned feature and are not available in the current version. The syntax below shows the intended design for a future release. For now, use the built-in resolvers or write concrete implementations directly. :::

The planned syntax for custom resolvers:

// PLANNED — not yet implemented
resolver my_cache_resolver for intent cache {
    fn resolve(config: CacheConfig) -> impl CacheProvider {
        // Concrete implementation that satisfies CacheProvider trait
    }
}

When available, custom resolvers will follow the same pipeline as built-in resolvers: they will generate code that is type-checked and contract-verified before compilation. This extensibility will allow organizations to define domain-specific intents that encode their infrastructure patterns.

Verification Guarantees

Every resolved implementation must satisfy:

  1. Type safety — All generated code passes the type checker.
  2. Contract compliance — All requires/ensures clauses on generated and referenced functions are verified.
  3. Ownership rules — No ownership violations in generated code.
  4. Callee preconditions — All called functions’ preconditions are satisfiable.

If any verification fails, the compiler emits an E0401 error pointing to the intent block, with details about which contract or type constraint was violated.

Inspecting Intent Resolution

Intent resolution is fully deterministic and transparent. The same input always produces the same output.

# Show what each intent resolves to
kodoc intent-explain my_app.ko

# Build with full certificate including intent resolution details
kodoc build my_app.ko -o my_app
# Check the .ko.cert.json for intent metadata

There is no hidden behavior — every resolver step is traceable, and the generated code is included in documentation output. This is critical for human auditability of AI-generated systems.

Next Steps

  • Agent Traceability — authorship tracking and confidence enforcement
  • Contracts — preconditions and postconditions verified by Z3
  • Testing — writing and running tests for intent-based modules