Languages: Communication Protocols for Agents
Understanding Languages in AD4M
In AD4M, Languages are the fundamental building blocks that define how agents communicate and share data. While we call them "Languages", they could just as well be called "Protocols" or "Data Storage Adapters" – they define the rules and mechanisms by which nodes in the network exchange information.
The term "Language" was chosen deliberately: just as human languages enable people to communicate and share ideas, AD4M Languages enable digital agents to exchange data and interact. Alternative metaphors could have been "Games" or "Dances" – patterns of interaction between agents.
Core Mechanism
At their heart, Languages implement a simple but powerful mechanism:
- Storage: Take some data, store it in a shared space (could be a server, Holochain DHT, blockchain, etc.), and return a URI that points to that data
- Retrieval: Take a URI and return the previously stored data (called an "Expression" in AD4M)
This mechanism creates a universal way for agents to share and reference information, regardless of where or how it's actually stored. For example:
- An IPFS Language might store data in the IPFS network and return a CID
- A Holochain Language might store data in a DHT and return an entry hash
- A Web2 Language might store data on a server and return a URL
Universal Addressing Mechanism
AD4M's Language system extends the familiar URI/URL model into a truly universal addressing scheme. Every Expression (the signed data objects in AD4M) is addressable through a URI that combines:
- The Language's unique identifier (a hash of its implementation code)
- The Language-specific address for that data
For example:
<language_hash>://<language-specific-address>
This means AD4M can seamlessly integrate with and extend existing addressing systems:
- Web URLs become:
http://example.com/resource
- IPFS content becomes:
QmIPFS123://<cid>
- Agent DIDs become:
did:key:z6Mk...
- Custom protocols become:
QmCustom789://user123/post456
The Language-Language (one of AD4M's bootstrap Languages) makes this system dynamic and extensible:
- New Languages can be published and their code verified
- Any AD4M instance can discover and install Languages as needed
- The system can evolve without central coordination
This creates a spanning layer across the internet where:
- Every piece of data has a globally unique address
- Addresses are self-describing (include their protocol)
- New protocols can be added dynamically
- Existing systems can be integrated seamlessly
Why Languages Matter
Languages in AD4M serve several crucial purposes:
- Define how data is stored and retrieved
- Specify how agents communicate
- Enable different storage backends (IPFS, Holochain, centralized servers, etc.)
- Allow for extensible and pluggable protocols
- Create semantic meaning through shared understanding
Technical Implementation
At its core, AD4M is a Language runtime. Languages are implemented as JavaScript modules that run in a sandboxed Deno environment within the AD4M executor. This provides:
- Secure execution environment
- TypeScript support out of the box
- Modern ES module system
- Built-in permissions model
Language Module Contract
Every Language module must export a default create
function with this signature:
export default function create(context: LanguageContext): Language | Promise<Language>
This function is the entry point for your Language. The AD4M executor will:
- Load your Language module in the Deno sandbox
- Call the
create
function with aLanguageContext
- Use the returned Language object to interact with your implementation
The LanguageContext
The LanguageContext
provides essential services and capabilities to your Language:
interface LanguageContext {
// Access to the agent's signing capabilities
agent: AgentService;
// For verifying signatures
signatures: SignaturesService;
// Path for persistent storage
storageDirectory: string;
// Language-specific settings
customSettings: object;
// Access to Holochain functionality
Holochain?: HolochainLanguageDelegate;
// For handling AD4M signals
ad4mSignal: Ad4mSignalCB;
}
Key features provided by the context:
-
Agent Service
// Sign expressions with the agent's keys const expression = context.agent.createSignedExpression(data); // Get the agent's DID const did = context.agent.did;
-
Holochain Integration
// Register a Holochain DNA await context.Holochain.registerDNAs([{ file: dnaPath, nick: 'my-dna' }]); // Call Holochain zome functions const result = await context.Holochain.call( 'my-dna', 'zome-name', 'function-name', payload );
-
Storage and Settings
// Access persistent storage const storagePath = context.storageDirectory; // Use custom settings const settings = context.customSettings;
The Language Interface
Here's the core interface that all Languages must implement:
interface Language {
// Required: Name of the language
readonly name: string;
// Optional adapters for different functionalities:
// For languages that store and retrieve expressions
readonly expressionAdapter?: ExpressionAdapter;
// For languages that handle UI rendering
readonly expressionUI?: ExpressionUI;
// For languages that manage links (used in Neighbourhoods)
readonly linksAdapter?: LinkSyncAdapter;
// For real-time presence and p2p signals
readonly telepresenceAdapter?: TelepresenceAdapter;
// For direct messaging between agents
readonly directMessageAdapter?: DirectMessageAdapter;
// For language-specific settings UI
readonly settingsUI?: SettingsUI;
// Optional: Mark expressions as immutable for caching
isImmutableExpression?(expression: Address): boolean;
// Define available interactions with expressions
interactions(expression: Address): Interaction[];
}
Language interface in the API reference | Language.ts in the codebase (opens in a new tab)
Types of Languages
AD4M supports several types of Languages for different purposes:
-
Expression Languages
- Store and retrieve data
- Most common type
- Example: IPFS-based file storage
-
Link Languages
- Core building block of Neighbourhoods
- Enable shared semantic spaces
- Example: Holochain-based p2p links
-
Direct Message Languages
- Enable agent-to-agent communication
- Support private messaging
- Example: Encrypted p2p messaging
Working with Languages
The Core Expression Mechanism
Before diving into examples, it's important to understand that most Languages (all basic "Expression Languages") operate around the same core pattern:
interface ExpressionAdapter {
// Store data and get a reference
putAdapter: {
createPublic(content: object): Promise<Address>;
// or for read-only languages:
addressOf(content: object): Promise<Address>;
};
// Retrieve data using its reference
get(address: Address): Promise<Expression | null>;
}
This simple pattern enables AD4M to create a web of semantic references, where any piece of data can be stored and referenced by its address, regardless of the underlying storage mechanism.
Installing Languages
// Install a language from its address
await ad4m.languages.install("Qm...");
// List all installed languages
const languages = await ad4m.languages.all();
Publishing Languages
// Publish a new language
const address = await ad4m.languages.publish({
name: "my-language",
description: "A custom language implementation",
sourceCodeLink: "https://github.com/...",
bundle: languageBundle
});
Using Languages
// Create an expression in a language
const expression = await ad4m.expression.create(
languageAddress,
{ content: "Hello, World!" }
);
// Retrieve an expression
const retrieved = await ad4m.expression.get(expression.address);
Built-in Languages
AD4M comes with several bootstrap languages:
- Agent Language: Resolves DIDs to agent information
- Language Language: Manages language publication and installation
- Perspective Language: Handles perspective storage and sharing
- Neighbourhood Language: Enables creation of shared spaces
Security Considerations
Languages run in a sandboxed environment with:
- Controlled access to system resources
- Explicit permission model
- Isolated execution context
- Secure communication channels
For a detailed guide on creating your own Language, see the Language Development Guide.
Language Templates
To help you get started with creating your own languages, we have provided some templates that you can use as a starting point. These templates are Deno compatible and provide a basic structure for your language.
- Expression Language without DNA template (opens in a new tab)
- Expression Language with DNA template (opens in a new tab)
- Link Language without DNA template (opens in a new tab)
- Link Language with DNA template (opens in a new tab)
You can clone these repositories and modify them to create your own language. Remember to follow the guidelines for making your language Deno compatible.