A context-building execution engine for AI-native programming
Idyll Engine reimagines programming for the AI era. Instead of functions that transform data and produce side effects, Idyll functions build context that AI interprets to determine relevance. This paradigm shift enables a new form of programming where execution is exploration and results are contextual understanding.
- Philosophy: Context-Driven Computation
- Computational Insights
- How This Changes AI Programming
- Core Features
- Installation
- Quick Start
- Why This Matters
- Grammar and Language Design
- Technical Details
- CLI Usage
- API Reference
- Examples
- Development
- Documentation
- The Vision: Community-Driven Intelligence Construction
- Community
- License
- Acknowledgments
- Citation
The Idyll language fundamentally reimagines programming for the AI era. Instead of functions that transform data and produce side effects, Idyll functions build context that AI interprets to determine relevance.
Traditional Programming: Execute → Transform → Return
Idyllic Programming: Execute → Augment Context → AI Interprets
In Idyllic, function calls don't just compute—they accumulate context. The AI model becomes the interpreter of this context, extracting what matters for the task at hand. This mirrors how human intelligence works: we gather information, build understanding, and extract meaning based on intent.
Idyllic embraces true homoiconicity—programs are documents, documents are programs. An <agent> definition isn't just configuration, it's executable context. Custom functions aren't subroutines, they're documented patterns of context accumulation. The XML structure is both human-readable documentation and machine-executable code.
Functions contribute to an ever-growing context rather than producing isolated results. Each function call enriches the computational environment.
No recursion, no complex control flow—just sequential context building. This maps perfectly to how transformer models process information.
Variables aren't memory locations but prompts for context-aware resolution. <variable name="topic" prompt="What to search for" /> asks the AI to resolve based on accumulated context.
The middleware system acts as a compression layer, distilling verbose execution results into what the AI actually needs—solving the context window problem elegantly.
Traditional: "Call function X to get result Y"
Idyllic: "Call function X to add context, let AI determine relevance"
Traditional: Manage state across function calls
Idyllic: State IS the accumulated context flow
Traditional: Explicitly handle every case
Idyllic: Patterns emerge from context interpretation
Traditional: "How to compute"
Idyllic: "What context to build"
Just as humans resolve everything into the visual domain in working memory, Idyllic resolves all values into rich, composable strings with references and pointers. The context becomes the working memory.
Our strings aren't just text - they're augmented with semantic markers:
<content>
Analyze <mention:document id="doc123">the architecture doc</mention:document>
and compare with <mention:user id="usr456">John's</mention:user> proposal
focusing on <variable name="aspect" prompt="What aspect to analyze"/>
<annotation confidence="0.8">This seems related to last week's discussion</annotation>
</content>These augmentations create a rich semantic graph within the text:
- Mentions create explicit references to entities (documents, users, agents)
- Variables are prompts for contextual resolution, not static values
- Annotations add metadata and confidence layers
- Links preserve external references while maintaining readability
We layer a lightweight execution engine on top of XML that adds context-driven semantics:
- Sequential Context Building - Each function call adds to accumulated context
- Variable Resolution - AI resolves variables based on accumulated context, not static scope
- Error Resilience - Failed functions still contribute partial context
- Semantic Preservation - The meaning is in the text + augmentations, not in types
The real power comes from functional combinators that work with context:
<!-- Combinator: Sequential exploration -->
<function title="Deep Analysis">
<fncall fn="explore:surface">Initial exploration</fncall>
<fncall fn="explore:patterns">Find patterns in previous context</fncall>
<fncall fn="explore:anomalies">What doesn't fit the patterns?</fncall>
</function>
<!-- Combinator: Parallel perspectives -->
<function title="Multi-Perspective Analysis">
<fncall fn="analyze:technical">Technical implications</fncall>
<fncall fn="analyze:business">Business impact</fncall>
<fncall fn="analyze:user">User experience angle</fncall>
<fncall fn="synthesize:perspectives">Combine all viewpoints</fncall>
</function>These aren't traditional function compositions - they're context combinators that build understanding.
This design choice is fundamental:
- Variables in natural language rather than rigid JSON schemas
- Intent expression through string interpolation:
"Find breakthroughs in <variable name='field'/>" - Context accumulation means programs move forward even through errors
- Non-brittle by design - unlike automation tools, this is an experimental programming paradigm
We deliberately chose expressiveness over efficiency. JSON schemas are faster but they cage intelligence. String interpolation with variables lets you experiment with AI capabilities at the speed of thought. You can always optimize later once patterns emerge.
Traditional automation breaks at the first unexpected input. Idyllic embraces the messiness of intelligence:
- Functions that error still contribute context
- Partial results are valid results
- The AI interprets accumulated context to recover and continue
- Each execution teaches you something about the problem space
This isn't about building reliable workflows - it's about constructing intelligence through experimentation.
- Context-Building Functions: Functions accumulate context rather than just returning values
- Homoiconic Documents: XML documents that are simultaneously code, data, and documentation
- AI-Native Variables: Variables resolved through context interpretation, not memory lookup
- Response Pipeline: Intelligent middleware that compresses execution context for AI consumption
- Linear Execution Model: Sequential context accumulation perfectly aligned with transformer architectures
- Custom Functions: Reusable patterns of context accumulation, not traditional subroutines
- Instrumentation Hooks: Complete observability into context building with timing and result tracking
# npm
npm install @idyllic-labs/idyll-engine
# yarn
yarn add @idyllic-labs/idyll-engine
# pnpm
pnpm add @idyllic-labs/idyll-engine
# bun
bun add @idyllic-labs/idyll-engineimport { parseXmlToAst, DocumentExecutor, createFunctionRegistry, defineFunction } from '@idyllic-labs/idyll-engine';
// Functions that build context, not just transform data
const functions = createFunctionRegistry({
'search:web': defineFunction({
schema: z.object({ query: z.string() }),
description: 'Add search results to context',
execute: async (params, content, context) => ({
results: ['result1', 'result2'],
searchedFor: params.query,
// This becomes part of the accumulated context
}),
}),
'ai:summarize': defineFunction({
schema: z.object({ style: z.string() }),
description: 'Summarize accumulated context',
execute: async (params, content, context) => ({
// Access previous results from context
summary: `Summarized ${context.previousResults.size} previous operations`,
basedOn: Array.from(context.previousResults.keys()),
}),
}),
});
// Documents are programs - homoiconicity in action
const document = parseXmlToAst(`
<document>
<p>Research Task</p>
<fncall idyll-fn="search:web">
<params>{"query": "AI breakthroughs"}</params>
<content>Search for latest developments</content>
</fncall>
<fncall idyll-fn="ai:summarize">
<params>{"style": "bullet-points"}</params>
<content>Summarize the findings</content>
</fncall>
</document>
`);
// Execute with instrumentation to observe context building
const executor = new DocumentExecutor({
functions,
hooks: {
afterExecution: (fn, result, duration) => {
console.log(`Context augmented by ${fn} in ${duration}ms`);
}
}
});
const report = await executor.execute({
mode: 'document',
document,
options: { functions }
});import { Agent, parseXmlToAst } from '@idyllic-labs/idyll-engine';
// Agents are documents - code and documentation unified
const agentProgram = parseXmlToAst(`
<agent name="Research Assistant">
<p>I help with research by building context through function calls.</p>
<!-- Custom function: a reusable pattern of context accumulation -->
<function title="Deep Research" icon="🔬">
<function:definition>
<fncall idyll-fn="search:web">
<params>{"maxResults": 10}</params>
<content>Search for <variable name="topic" prompt="Research topic" /></content>
</fncall>
<fncall idyll-fn="analyze:relevance">
<params>{}</params>
<content>Filter for <variable name="criteria" prompt="Relevance criteria" /></content>
</fncall>
<fncall idyll-fn="format:report">
<params>{}</params>
<content>Format findings</content>
</fncall>
</function:definition>
</function>
</agent>
`);
// The agent interprets accumulated context
const agent = new Agent({
program: agentProgram,
model: aiModel,
functions: contextBuildingFunctions,
responseMiddleware: [
// Compress verbose context into what matters
contextCompressionMiddleware
]
});
// Variables are resolved through context, not assignment
const result = await agent.chat([
{ role: 'user', content: 'Research quantum computing breakthroughs' }
]);Idyllic represents a fundamental shift in how we think about programming in the AI era. By treating computation as context accumulation rather than data transformation, we align programming with how AI models naturally process information.
The homoiconic nature means every program is simultaneously:
- Executable code that builds context
- Living documentation that explains intent
- AI-readable structure that guides interpretation
This isn't just a new syntax—it's a new computational philosophy where meaning emerges from context, intelligence interprets accumulation, and programming becomes a conversation between human intent and AI understanding.
The choice of XML is deliberate and strategic:
- Ease of Parsing - Well-established parsers, no ambiguity in structure
- Tooling Ecosystem - XPath, XSLT, schema validation, editor support
- LLM Familiarity - Extensive XML in training data means AI models understand it intuitively
- Extensible Markup - Literally designed for interweaving text with structure
- Homoiconicity - Natural representation where code structure mirrors data structure
Idyllic adds a light execution layer with context-driven semantics on top of XML. This enables:
- Explorative Context Engineering - Build up context iteratively through function calls
- Intelligence Design - Create patterns of context accumulation that guide AI behavior
- Semantic Clarity - Each element has clear meaning in the context-building process
- Augmented Strings - Text enriched with mentions, variables, and annotations
- Context Combinators - Functions that compose to build understanding, not just transform data
(* Root Elements *)
document ::= <document [id] [version]> block* </document>
agent ::= <agent [id] [name] [model]> block* </agent>
diff ::= <diff> operation+ </diff>
(* Blocks - The Core Building Units *)
block ::= content-block | executable-block | function-block
(* Content Blocks - Rich Text and Structure *)
content-block ::= paragraph | heading | list-item | code | quote | separator | data
paragraph ::= <p> rich-content </p>
heading ::= <h[1-6]> rich-content </h[1-6]>
list-item ::= <bulletlistitem> rich-content </bulletlistitem>
| <numberedlistitem> rich-content </numberedlistitem>
| <checklistitem checked> rich-content </checklistitem>
code ::= <code [language]> text </code>
quote ::= <quote [author] [source]> rich-content </quote>
separator ::= <separator/>
data ::= <data [title]> text </data>
(* Executable Blocks - Context Building *)
executable-block ::= function-call | trigger
function-call ::= <fncall idyll-fn="module:function">
[<params> json </params>]
[<content> rich-content </content>]
</fncall>
trigger ::= <trigger event="string" [debounce]>
[<params> json </params>]
</trigger>
(* Function Blocks - Custom Context Patterns *)
function-block ::= <function title="string" [icon]>
[<function:description> text </function:description>]
<function:definition>
(content-block | executable-block)+
</function:definition>
</function>
(* Rich Content - Inline Elements *)
rich-content ::= (text | styled-text | mention | variable | link | annotation)*
styled-text ::= <strong> rich-content </strong>
| <em> rich-content </em>
| <code> rich-content </code>
| <u> rich-content </u>
| <s> rich-content </s>
mention ::= <mention:[type] id [label]> text </mention:[type]>
variable ::= <variable name [prompt]> [text] </variable>
link ::= <a href> rich-content </a>
annotation ::= <annotation [title] [comment]> rich-content </annotation>
(* Function Naming Convention *)
function-name ::= [module ":"] identifier
module ::= js-identifier
identifier ::= js-identifier
js-identifier ::= /[a-zA-Z_$][a-zA-Z0-9_$]*/- Flat Structure - No deeply nested containers, promoting linear context flow
- Rich Content Everywhere - Text can contain variables, mentions, and styling
- Function Calls as First-Class -
<fncall>blocks are primary building units - Custom Functions - Define reusable context-building patterns inline
- Variables in Content - Not separate from text but embedded within it
The grammar enforces the philosophy: programs are documents, execution builds context, and meaning emerges from accumulation.
All functions follow the module:function pattern with JavaScript identifier constraints:
import { validateFunctionName, toAzureFunctionName } from '@idyllic-labs/idyll-engine';
// Valid function names
'demo:echo' // ✅
'ai:analyzeText' // ✅
'processData' // ✅ (no module)
// Invalid (no longer supported)
'ai:analyze-text' // ❌ kebab-case not allowed
// Azure Functions compatibility
toAzureFunctionName('demo:echo') // → 'demo--echo'# Parse a document
bun run cli parse examples/document-simple.xml
# Validate a document
bun run cli validate examples/agent-simple.xml
# Execute a document
bun run cli execute examples/executable-demo.xml
# Run agent CLI
bun run agent examples/demo-agent.xmlparseXML(xml: string)- Parse Idyllic XML to ASTvalidateDocument(document, context?)- Validate document structurecreateFunctionRegistry(functions)- Create a function registrydefineFunction(config)- Define a function with schema and executor
Agent- AI agent with function execution and memoryActivityMemory- Memory management for agent interactionsgetModel(modelId)- Get AI model instance
toAzureFunctionName(functionName)- Convert to Azure-compatible namesvalidateFunctionName(functionName)- Validate function name formatparseFunctionName(functionName)- Parse module and function parts
Explore our comprehensive examples:
document-simple.xml- Basic document structureexecutable-demo.xml- Document with function callsagent-simple.xml- Simple agent definitiondemo-agent.xml- Agent with custom functions
instrumentation-demo.ts- Execution hooks and timingcustom-function-instrumentation-demo.ts- Multi-level context buildingrecursion-test.ts- Understanding linear execution modelfunction-execution-demo.ts- Direct function execution
Run any TypeScript example:
bun run examples/instrumentation-demo.ts# Install dependencies
bun install
# Build the package
bun run build
# Run type checking
bun run typecheck
# Run tests
bun run test
# Start agent CLI
bun run agent- Manifesto - Our philosophy and vision for AI programming
- Document Execution Specification - Complete execution model
- Agent System - Agent architecture details
Imagine a world where complex AI capabilities emerge from a community-contributed registry of context-building functions:
community-functions/
├── analysis/
│ ├── code-understanding # Analyze codebases through context
│ ├── sentiment-evolution # Track sentiment across context
│ └── causal-extraction # Extract cause-effect relationships
├── synthesis/
│ ├── cross-domain-insights # Connect ideas across domains
│ ├── analogy-discovery # Find patterns in different contexts
│ └── thesis-construction # Build arguments from evidence
└── specialized/
├── legal-precedent-analysis
├── medical-differential-diagnosis
└── architecture-migration-planning
The key insight: You're not building agents - you're constructing intelligence by giving AI composable context-building blocks.
Traditional approach to complex task: Breaks. Too brittle. Too many edge cases.
Idyllic approach: AI naturally composes functions to build understanding:
- Each function adds context
- AI determines relevance and relationships
- Complex intelligence emerges from simple primitives
- No fragile control flow needed
This is the future we're building towards.
- Website: idyllic.so - SaaS version of the engine
- Blog: idyllic.so/blog
- Discord: Join our community
- Twitter: @idylliclabs
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Copyright 2024 Idyllic Labs
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
- Built with Bun for blazing fast development
- Inspired by the pioneers of homoiconic languages (Lisp, Mathematica)
- Special thanks to the AI/ML community for pushing the boundaries of what's possible
- Wordware - For demonstrating the power of context and documents as programming substrate
- Notion - Pioneered block-based documents that inspired our execution model
- BlockNote - Our grammar structure is based on their schema design
- Paul Graham - For his foundational work on Lisp and homoiconicity
- LangChain - Demonstrated the importance of composability in AI systems
- Claude Code - Our collaborative AI partner in designing this language
If you use Idyll Engine in your research, please cite:
@software{idyll-engine,
author = {Idyllic Labs},
title = {Idyll Engine: A Context-Building Execution Engine for AI-Native Programming},
year = {2024},
url = {https://github.com/idyllic-labs/idyll-engine},
note = {Available at: \url{https://idyllic.so}}
}