name: at-language-expert
description: Essential procedural knowledge and constraints for writing, debugging, and understanding the at programming language.
at Language Agent Skill
This skill provides the mandatory procedural knowledge required to successfully write and debug at code. at is a fast, strictly-typed language built specifically for AI agents.
Design Philosophy
at is designed around what makes agents succeed, informed by A Language For Agents:
- Context without LSP: Types are explicit in function signatures and return types. You never need an LSP to understand what a function accepts or returns. Local variables use inference to save tokens, but the public API is always readable.
- Braces over whitespace:
atuses{ }delimiters, not significant whitespace. This avoids the token-efficiency and surgical-edit problems that LLMs have with indentation-sensitive languages. - Results over exceptions: Prefer
Result<T, E>and?propagation.try/catch/finallyexists as an escape hatch butResultis the idiomatic error-handling pattern. Agents should default to returningResulttypes. - Explicit effects: Side effects (network, filesystem, time, randomness) must be declared via
needs { ... }blocks. This makes mocking trivial in tests and gives agents clear signals about what a function touches. - Minimal diffs: Trailing commas are supported everywhere (arrays, maps, match arms, function params). Format code vertically to keep diffs single-line.
- Greppable imports: All imports require aliasing (
import "x" as y;). Every symbol use is prefixed with its module name (like Go'scontext.Context), making code searchable with basic tools likegreporsed. - Local reasoning: Each file is self-contained. No implicit globals, no re-exports, no barrel files. If you read a file, you can understand it without loading other files.
- No macros:
athas no macro system. Code generation is unnecessary when the cost of writing code is low. - No re-exports or barrel files: Every import points to the file that defines the symbol. One-to-one mapping from declaration to usage.
- Dependency-aware builds: No circular imports. Packages have clear boundaries. Test results are aggressively cached.
- Deterministic tests: Tests can pin time and randomness (
using time.fixed; using rand.seeded;), eliminating flakiness by design. - Single failure condition:
at checktype-checks and lints in one pass. Code either passes or fails — there is no "compiles but has type errors" state.at testruns all tests. Two commands, zero ambiguity.
Critical Constraints (Read First)
- Explicit Return Types Required: Every function MUST declare its return type
fn name() -> type {. - Mandatory Import Aliasing: You MUST alias all imports (
import "./utils.at" as utils;). There are no global imports, no re-exports. - Capability Sandboxing: If a script touches the network, filesystem, or time, you MUST declare a
needs { ... }block. - Token Efficiency: The compiler infers local variables. Use
let x = 5;instead oflet x: int = 5;to save tokens. - Mutation uses
set: Variables are immutable by default. Useset x = newValue;to mutate (notlet mut). - Semicolons required: All statements end with
;. - Match arms use commas: Match arms are separated by
,(not newlines). - No macros: There is no macro system. Write explicit code.
- Prefer
Resultovertry/catch: UseResult<T, E>and?for error handling. Avoidtry/catchunless wrapping FFI or legacy code.
1. Syntax Overview
Variables & Types
let immutable = 10;
let mutable = 20;
set mutable = 30; // `set` for mutation, not `let mut`
// Type inference handles these automatically
let array = [1, 2, 3];
let empty = []; // empty array literal
let m = map {}; // empty map literal
let m2 = map { "key": "value" };
Functions & Tests
Tests are colocated and execute at highly-optimized speeds with at test.
fn add(a: int, b: int) -> int {
return a + b;
}
test "adds numbers" {
assert(add(1, 2) == 3);
}
Control Flow
if a > b {
// ...
} else {
// ...
}
for item in array {
// ...
}
while condition {
// ...
}
Error Handling
Use Result<T, E> and ? for early returns. This is the idiomatic pattern — agents should default to this over try/catch.
fn divide(a: int, b: int) -> Result<int, string> {
if b == 0 {
return Err("Division by zero");
}
return Ok(a / b);
}
fn calculate() -> Result<int, string> {
let result = divide(10, 2)?;
return Ok(result + 1);
}
Enums & Pattern Matching
enum Shape {
Circle(float),
Rect(float, float), // multi-field variants supported
Point, // no-payload variant
}
fn area(s: Shape) -> float {
return match s {
Shape::Circle(r) => 3.14159 * r * r,
Shape::Rect(w, h) => w * h,
Shape::Point => 0.0,
};
}
Higher-Order Functions
map, filter, and reduce are compiler-inlined (not regular builtins):
let nums = [1, 2, 3, 4, 5];
let doubled = map(nums, |x| x * 2);
let evens = filter(nums, |x| x % 2 == 0);
let total = reduce(nums, 0, |acc, x| acc + x);
2. Builtins Reference
Core
print(value), assert(condition), assert_eq(a, b), len(collection), type_of(value)
Math
abs(n), min(a, b), max(a, b), floor(f), ceil(f), round(f), pow(base, exp), sqrt(f), sum(array)
String
contains(haystack, needle) (works on arrays and strings), slice(arr, start, end), split(str, delim), trim(str), to_upper(str), to_lower(str), substring(str, start, end), join(array, sep), replace(str, old, new), starts_with(str, prefix), ends_with(str, suffix), repeat(str, n), parse_int(str), parse_float(str), to_string(value)
Character
char_code(str), from_char_code(n), is_digit(str), is_alpha(str), is_upper(str), is_lower(str)
Array
append(arr, value), sort(arr), reverse(arr), index_of(arr, value), count(arr, value), range(start, end)
Map
keys(map), values(map)
Regex
regex_match(str, pattern) -> bool, regex_find(str, pattern) -> array<string>, regex_replace(str, pattern, replacement) -> string
Note: Use {{ to escape literal { in regex patterns inside string literals (e.g., "[0-9]{{3}}" for the regex [0-9]{3}).
Option & Result
some(v), none(), is_some(opt), is_none(opt), ok(v), err(v), is_ok(res), is_err(res)
3. Explicit Effects & Sandboxing
Agents execute in a secure sandbox. You cannot perform side-effects without declaring them statically.
needs { network, fs } // MUST be declared if you fetch or read files
import "std/http.at" as http;
fn fetch_data() -> Result<string, string> {
return http.get("https://example.com");
}
For test determinism, declare deterministic environments:
using time.fixed;
using rand.seeded;
4. Code Generation Checklist for LLMs
Before modifying or generating at code, verify:
- Mutation: Use
set x = value;to mutate, notlet mut. - Error handling: Use
Result<T, E>and?, nottry/catch. - Formatting: Multi-element arrays, tuples, and maps MUST be formatted vertically to preserve diff-stable trailing commas.
- Aliasing: Did you alias all imports? (
import "x" as y;) - Effects: Did you declare
needs { ... }at the top of the file if accessing external systems? - Tests: Are you writing colocated
test "name" { assert(...); }blocks for your functions? - Types: Did you let the compiler infer types for local variables using
let x = ...? - Semicolons: All statements end with
;. - Match commas: Match arms separated by
,. - Mixed arithmetic:
intandfloatcan be mixed freely (int is promoted to float). - No macros: Write explicit code. There is no macro system.
- Local reasoning: Each file should be self-contained. No re-exports, no barrel files.
5. Development CLI
As an agent, you can use these tools to iteratively validate your code:
at check- Type-check and lint in one pass (instant, catches all errors before runtime)at test <file|dir>- Run tests in a file or recursively in a directory (aggressively cached, very fast feedback loop)at run <file>- Execute a scriptat fix- Auto-formats code and fixes lints
6. Limitations
These are things at intentionally does not support or has not yet implemented:
- No classes or inheritance. Only structs and enums (algebraic data types).
- No mutable references. All data is immutable/copy-on-write (
Rc-shared).setcreates new copies. - No standard I/O beyond
print. Noread_line, no file I/O builtins (would requirefscapability and corresponding builtins which do not exist yet). - No hash/set data structure. Only arrays and ordered maps. Use a map with dummy values as a workaround.
- No package manager. Remote imports are direct URL fetches with caching.
- No null. Uses
option(some/none) instead. - No implicit returns. Must use
returnkeyword (though block expressions have implicit tail values). - Integer arithmetic is overflow-checked. Large computations will error rather than wrap.
- Single-threaded. Async is cooperative, not parallel. No OS-level threading.
- No recursion depth guarantees. A configurable
max_frameslimit exists for sandboxed execution. - String interpolation uses
{expr}. Use{{to write a literal{in strings (relevant for regex patterns with quantifiers like{3}).
Related Documents
AI Artist — Engineering Specification
name: ai-artist-engineering-spec
Image Generation Skill
name: image-generation
Skill: Google Stitch for Content Visuals (MCP-Integrated)
name: google-stitch-content
Manage After Effects
description: Manage After Effects from Claude — create configs, build compositions, render videos, diagnose issues, and optionally generate AI content via Prompture