Expressions: Agent-Authored Data Objects
Understanding Expressions
In AD4M's agent-centric paradigm, all data is treated as a claim or statement made by an agent. These claims are called "Expressions" – following the metaphor of Languages, they are what agents "express" through different protocols (Languages). While they could be seen as simple data objects, Expressions are fundamentally different because they:
- Always include cryptographic proof of who created them
- Are always created through a specific Language
- Have globally unique addresses in AD4M's universal addressing scheme
Anatomy of an Expression
Every Expression consists of:
interface Expression {
// The DID of the agent who created this Expression
author: string;
// When the Expression was created
timestamp: string;
// The actual data/content
data: any;
// Which Language this Expression belongs to
language: LanguageRef;
// Cryptographic proof of authorship
proof: {
// These flags are added by AD4M during retrieval
valid?: boolean; // True if signature verification succeeded
invalid?: boolean; // True if signature verification failed
// The actual stored proof data
signature: string; // The cryptographic signature
key: string; // Key path in the author's DID Document used for signing
};
}
For example:
{
"author": "did:key:zQ3shv5VUAbtY5P1jGsPzy7L27FTxeDv2hnhVp9QT3ALNCnQ2",
"timestamp": "2023-06-21T14:47:48.935Z",
"data": "Hello World!",
"language": {
"address": "literal"
},
"proof": {
"valid": true, // Added by AD4M during retrieval
"invalid": false, // Added by AD4M during retrieval
"signature": "...", // The stored signature
"key": "..." // Key path in the author's DID Document used for signing
}
}
Global Addressing
Every Expression in AD4M has a unique address in the format:
<language_hash>://<expression_address>
This means:
- The Language's hash identifies how to interpret/resolve the address
- The expression_address is Language-specific (could be a CID, URL, hash, etc.)
- The full address is globally unique and resolvable by any AD4M instance
Working with Expressions
Creating Expressions
When an agent wants to share data, they create an Expression through a Language:
// Create an Expression using the literal Language
const url = await ad4m.expression.create(
"Hello World!",
"literal"
);
// Returns: literal://base64encoded-content
// Create an Expression using a custom Language
const socialPost = await ad4m.expression.create(
{ text: "My first post!" },
"QmSocialApp123" // Language hash
);
// Returns: QmSocialApp123://post789
Behind the scenes, AD4M:
- Passes the data to the specified Language
- The Language stores/processes the data and returns an address
- AD4M signs the Expression with the agent's keys
- Returns the full Expression URL
Retrieving Expressions
Any agent can retrieve an Expression using its address:
const expression = await ad4m.expression.get("QmSocialApp123://post789");
The retrieved Expression includes:
- The original data
- Who created it (author DID)
- When it was created
- Cryptographic proof of authenticity
Signature Verification
When you retrieve an Expression through ad4m.expression.get()
, AD4M automatically:
- Resolves the author's DID to get their public keys
- Verifies that the signature matches:
- The author's DID
- The Expression's data
- The timestamp
- Using the specified key from the author's DID Document
- Enriches the Expression object with verification flags:
proof.valid
: Set totrue
if verification succeededproof.invalid
: Set totrue
if verification failed
These verification flags are not stored with the Expression – they are computed on-the-fly during retrieval to ensure fresh verification against the current state of the author's DID Document.
// When you retrieve an Expression
const expression = await ad4m.expression.get("QmSocialApp123://post789");
// AD4M has already verified the signature
if (expression.proof.valid) {
// The Expression is authentic and unmodified
console.log("Verified expression from:", expression.author);
} else {
// The signature verification failed
console.warn("Could not verify expression authenticity");
}
Expression Types
While Expressions can contain any type of data, there are several common patterns:
-
Literal Expressions
- Simple data types (strings, numbers, objects)
- Encoded directly in the address
- Example:
literal://base64encoded-content
-
Content Expressions
- Larger data objects (posts, documents, media)
- Stored in a distributed system (IPFS, Holochain, etc.)
- Example:
QmSocialApp123://post789
-
Reference Expressions
- Point to data in other systems
- Act as bridges to existing protocols
- Example:
http://example.com/resource
Expressions and Trust
The agent-centric nature of Expressions enables a web of trust:
- Authenticity: Every Expression is cryptographically signed, so you can verify who created it
- Provenance: The timestamp and author create an audit trail
- Context: Expressions can be referenced and linked in Perspectives, creating semantic meaning
- Interoperability: Any AD4M instance can verify and interpret Expressions
Best Practices
When working with Expressions:
-
Choose the Right Language
- Use literal Language for simple, small data
- Use specialized Languages for specific data types
- Consider storage requirements and accessibility
-
Handle Verification
- Always check the
proof.valid
field - Consider the Expression's author in your trust model
- Use timestamps for temporal context
- Always check the
-
Think Agent-Centric
- Remember Expressions are claims made by agents
- Consider how Expressions fit into social contexts
- Use Perspectives to organize and give meaning to Expressions
For more details on implementing Languages that create and resolve Expressions, see the Language Development Guide.