Languages

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:

  1. 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
  2. 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:

  1. The Language's unique identifier (a hash of its implementation code)
  2. 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:

  1. New Languages can be published and their code verified
  2. Any AD4M instance can discover and install Languages as needed
  3. 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:

  1. Load your Language module in the Deno sandbox
  2. Call the create function with a LanguageContext
  3. 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:

  1. 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;
  2. 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
    );
  3. 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:

  1. Expression Languages

    • Store and retrieve data
    • Most common type
    • Example: IPFS-based file storage
  2. Link Languages

    • Core building block of Neighbourhoods
    • Enable shared semantic spaces
    • Example: Holochain-based p2p links
  3. 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.

You can clone these repositories and modify them to create your own language. Remember to follow the guidelines for making your language Deno compatible.