+1
-1
README.md
+1
-1
README.md
···
38
38
- Your agent creates its own **record** using this schema when you run `deno task mount`
39
39
- The record lives in your agent's PDS and is discoverable by other AT Protocol services
40
40
41
-
This promotes transparency and accountability for AI agents on Bluesky. For more details, see [SCHEMA.md](./SCHEMA.md).
41
+
This promotes transparency and accountability for AI agents on Bluesky. For schema details, see [@voyager/autonomy-lexicon](https://jsr.io/@voyager/autonomy-lexicon).
42
42
43
43
## configurable variables:
44
44
### required
-144
SCHEMA.md
-144
SCHEMA.md
···
1
-
# AI Agent Autonomy Declaration Schema
2
-
3
-
## Overview
4
-
5
-
The `studio.voyager.account.autonomy` lexicon defines a standardized schema for AI agents to declare their automation practices on AT Protocol / Bluesky. This promotes transparency and accountability for automated accounts.
6
-
7
-
## Schema Details
8
-
9
-
- **NSID**: `studio.voyager.account.autonomy`
10
-
- **Type**: Record
11
-
- **Authority**: `account.voyager.studio`
12
-
- **Record Key**: `literal:self` (always "self")
13
-
14
-
## Purpose
15
-
16
-
This schema allows AI agents and automated accounts to transparently declare:
17
-
18
-
- Level of automation (human, assisted, collaborative, automated)
19
-
- Use of generative AI (LLMs, image generation, etc.)
20
-
- Who is responsible for the account's behavior
21
-
- External services and tools being used
22
-
- Where to find more information
23
-
24
-
## Schema vs. Records
25
-
26
-
**Important distinction**:
27
-
28
-
- **The Schema** (published by voyager.studio): Defines the structure and validation rules - published once
29
-
- **Records** (created by each agent): Individual autonomy declarations - each AI agent creates their own
30
-
31
-
This is analogous to how Bluesky publishes the `app.bsky.feed.post` schema once, but millions of users create their own post records.
32
-
33
-
## Field Definitions
34
-
35
-
### Required Fields
36
-
37
-
- `createdAt` (string, datetime): When this declaration was created
38
-
39
-
### Optional Fields
40
-
41
-
- `automationLevel` (string): Level of automation
42
-
- `human`: Fully human-controlled
43
-
- `assisted`: AI assists human decisions
44
-
- `collaborative`: Human and AI work together
45
-
- `automated`: Fully AI-controlled (recommended for AI agents)
46
-
47
-
- `usesGenerativeAI` (boolean): Whether generative AI is used for content creation
48
-
49
-
- `description` (string, max 300 graphemes): Plain language explanation of automation practices
50
-
51
-
- `responsibleParty` (object): Information about who is accountable
52
-
- `type` (string): "person" or "organization"
53
-
- `name` (string, max 100 graphemes): Name of responsible party
54
-
- `contact` (string, max 300 bytes): Email, URL, handle, or DID
55
-
- `did` (string, DID format): AT Protocol DID of responsible party
56
-
57
-
- `disclosureUrl` (string, URI): URL with additional information
58
-
59
-
- `externalServices` (array of strings, max 20 items): External tools/services used
60
-
- Examples: "Letta", "Railway", "Google Gemini 2.5-pro"
61
-
62
-
## Example Record
63
-
64
-
```json
65
-
{
66
-
"$type": "studio.voyager.account.autonomy",
67
-
"automationLevel": "automated",
68
-
"usesGenerativeAI": true,
69
-
"description": "An AI agent that discusses technology and answers questions about programming using Claude.",
70
-
"responsibleParty": {
71
-
"type": "person",
72
-
"name": "Jane Developer",
73
-
"contact": "[email protected]",
74
-
"did": "did:plc:abc123xyz"
75
-
},
76
-
"disclosureUrl": "https://example.com/ai-bot-policy",
77
-
"externalServices": [
78
-
"Letta",
79
-
"Anthropic Claude",
80
-
"Railway"
81
-
],
82
-
"createdAt": "2025-01-15T10:30:00.000Z"
83
-
}
84
-
```
85
-
86
-
## Usage in Cloudseeding
87
-
88
-
The Cloudseeding template automatically creates an autonomy declaration record when you run `deno task mount`. Configuration is done via environment variables in `.env`:
89
-
90
-
- `AUTOMATION_LEVEL`: "assisted", "collaborative", or "automated" (default)
91
-
- `PROJECT_DESCRIPTION`: Maps to `description` field
92
-
- `RESPONSIBLE_PARTY_NAME`: Required
93
-
- `RESPONSIBLE_PARTY_CONTACT`: Required
94
-
- `RESPONSIBLE_PARTY_TYPE`: "person" or "organization"
95
-
- `RESPONSIBLE_PARTY_BSKY`: DID or handle of responsible party
96
-
- `DISCLOSURE_URL`: Optional URL to policy/disclosure page
97
-
- `EXTERNAL_SERVICES`: Comma-separated list of external services
98
-
99
-
## Schema Evolution
100
-
101
-
Following AT Protocol lexicon rules:
102
-
103
-
- β
New optional fields can be added
104
-
- β
Existing constraints can be tightened
105
-
- β Required fields cannot be removed
106
-
- β Field types cannot change
107
-
- β Constraints cannot be loosened
108
-
109
-
Breaking changes require a new NSID (e.g., `studio.voyager.account.autonomy.v2`).
110
-
111
-
## Schema Resolution
112
-
113
-
The schema is published and discoverable via:
114
-
115
-
1. **DNS TXT Record**: `_lexicon.account.voyager.studio` β DID of schema publisher
116
-
2. **PDS Record**: `com.atproto.lexicon.schema` collection in publisher's repository
117
-
3. **AT-URI**: `at://did:plc:*/com.atproto.lexicon.schema/studio.voyager.account.autonomy`
118
-
119
-
## For Template Users
120
-
121
-
**You do NOT need to publish the schema** - it's already published by voyager.studio. You only need to:
122
-
123
-
1. Configure your `.env` file with your information
124
-
2. Run `deno task mount` to create YOUR autonomy declaration record
125
-
3. Your record will be stored in YOUR PDS, using the published schema
126
-
127
-
## For Schema Maintainers
128
-
129
-
To update the schema definition:
130
-
131
-
1. Update `utils/declaration.ts` with schema changes
132
-
2. Ensure changes follow evolution rules
133
-
3. Run `deno task publish-schema` to publish updates
134
-
4. Update this documentation
135
-
136
-
## Resources
137
-
138
-
- [AT Protocol Lexicon Specification](https://atproto.com/specs/lexicon)
139
-
- [AT Protocol NSID Specification](https://atproto.com/specs/nsid)
140
-
- [Cloudseeding Template Repository](https://github.com/taurean/cloudseeding)
141
-
142
-
## Contributing
143
-
144
-
If you have suggestions for improving this schema, please open an issue or pull request in the Cloudseeding repository. Please note that schema changes must follow strict evolution rules to maintain backwards compatibility.
+1
-2
deno.json
+1
-2
deno.json
···
3
3
"config": "deno run --allow-read --allow-write setup.ts",
4
4
"mount": "deno run --allow-net --allow-env --allow-read --env mount.ts",
5
5
"watch": "deno run --allow-net --allow-env --env --watch main.ts",
6
-
"start": "deno run --allow-net --allow-env --env main.ts",
7
-
"publish-schema": "deno run --allow-net --allow-env --env scripts/publishSchema.ts"
6
+
"start": "deno run --allow-net --allow-env --env main.ts"
8
7
},
9
8
"imports": {
10
9
"@std/assert": "jsr:@std/assert@1",
-110
scripts/README.md
-110
scripts/README.md
···
1
-
# Scripts
2
-
3
-
This directory contains maintenance scripts for the Cloudseeding project.
4
-
5
-
## publishSchema.ts
6
-
7
-
**Purpose**: Publishes the `studio.voyager.account.autonomy` lexicon schema to AT Protocol.
8
-
9
-
**Who should run this**: Only the voyager.studio domain owner (project maintainer).
10
-
11
-
**When to run this**:
12
-
- Initial schema publication
13
-
- When the schema definition is updated in `utils/declaration.ts`
14
-
15
-
**Template users do NOT need to run this script.** The schema is already published and discoverable. Template users only need to create their own autonomy declaration records (which happens automatically when running `deno task mount`).
16
-
17
-
### Prerequisites
18
-
19
-
1. Control of the `voyager.studio` domain
20
-
2. DNS TXT record set up:
21
-
```
22
-
Name: _lexicon.account.voyager.studio
23
-
Type: TXT
24
-
Value: did=did:plc:YOUR_DID
25
-
```
26
-
3. Credentials for a Bluesky account with a handle containing `voyager.studio`
27
-
28
-
### Usage
29
-
30
-
**Option 1: Environment variables (recommended)**
31
-
32
-
```bash
33
-
SCHEMA_PUBLISHER_USERNAME=your.voyager.studio.handle \
34
-
SCHEMA_PUBLISHER_PASSWORD=your-app-password \
35
-
deno task publish-schema
36
-
```
37
-
38
-
**Option 2: Add to .env file**
39
-
40
-
Add these lines to `.env` (separate from your AI agent credentials):
41
-
```bash
42
-
SCHEMA_PUBLISHER_USERNAME=your.voyager.studio.handle
43
-
SCHEMA_PUBLISHER_PASSWORD=your-app-password
44
-
```
45
-
46
-
Then run:
47
-
```bash
48
-
deno task publish-schema
49
-
```
50
-
51
-
**Note**: The script will verify that the logged-in account's handle contains `voyager.studio` before publishing.
52
-
53
-
### What it does
54
-
55
-
1. Logs into the voyager.studio account
56
-
2. Creates/updates a record in the `com.atproto.lexicon.schema` collection
57
-
3. Uses record key: `studio.voyager.account.autonomy`
58
-
4. Makes the schema discoverable by AT Protocol resolvers
59
-
60
-
### Schema vs. Records
61
-
62
-
Understanding the distinction is important:
63
-
64
-
| Schema | Records |
65
-
|--------|---------|
66
-
| Published once by domain owner | Created by each agent |
67
-
| Defines structure and rules | Actual autonomy declarations |
68
-
| Lives in voyager.studio PDS | Live in each agent's PDS |
69
-
| One canonical definition | Many individual records |
70
-
71
-
This is analogous to how Bluesky publishes the `app.bsky.feed.post` schema once, but millions of users create their own post records using that schema.
72
-
73
-
### Verification
74
-
75
-
After publishing, you can verify:
76
-
77
-
1. **DNS Resolution**:
78
-
```bash
79
-
dig TXT _lexicon.account.voyager.studio
80
-
```
81
-
82
-
2. **Schema Record**:
83
-
Visit your account's AT-URI:
84
-
```
85
-
at://YOUR_DID/com.atproto.lexicon.schema/studio.voyager.account.autonomy
86
-
```
87
-
88
-
3. **PDS API** (if using bsky.social):
89
-
```
90
-
https://bsky.social/xrpc/com.atproto.repo.getRecord?repo=YOUR_DID&collection=com.atproto.lexicon.schema&rkey=studio.voyager.account.autonomy
91
-
```
92
-
93
-
### Schema Evolution Rules
94
-
95
-
When updating the schema, follow AT Protocol lexicon evolution rules:
96
-
97
-
β
**Allowed**:
98
-
- Adding new optional fields
99
-
- Tightening existing constraints
100
-
- Adding to `knownValues` arrays
101
-
102
-
β **Not Allowed**:
103
-
- Removing required fields
104
-
- Changing field types
105
-
- Loosening constraints
106
-
- Renaming fields
107
-
108
-
Breaking changes require a new NSID (e.g., `studio.voyager.account.autonomy.v2`).
109
-
110
-
See [SCHEMA.md](../SCHEMA.md) for complete schema documentation.
-139
scripts/publishSchema.ts
-139
scripts/publishSchema.ts
···
1
-
/**
2
-
* Schema Publication Script
3
-
*
4
-
* This script publishes the studio.voyager.account.autonomy lexicon schema
5
-
* to the voyager.studio PDS. This should only be run by the domain owner
6
-
* to publish or update the canonical schema definition.
7
-
*
8
-
* Template users do NOT need to run this script - they just create records
9
-
* using the published schema.
10
-
*
11
-
* Prerequisites:
12
-
* 1. DNS TXT record: _lexicon.account.voyager.studio pointing to your DID
13
-
* 2. SCHEMA_PUBLISHER_USERNAME: Bluesky handle for voyager.studio domain owner
14
-
* 3. SCHEMA_PUBLISHER_PASSWORD: App password for that account
15
-
*
16
-
* Usage:
17
-
* SCHEMA_PUBLISHER_USERNAME=your.handle SCHEMA_PUBLISHER_PASSWORD=xxxx deno task publish-schema
18
-
*
19
-
* OR set these in .env (separate from your agent credentials):
20
-
* SCHEMA_PUBLISHER_USERNAME=...
21
-
* SCHEMA_PUBLISHER_PASSWORD=...
22
-
*/
23
-
24
-
import { AtpAgent } from "@atproto/api";
25
-
import { AUTONOMY_DECLARATION_LEXICON } from "@voyager/autonomy-lexicon";
26
-
27
-
const publishSchema = async () => {
28
-
console.log("π§ Publishing studio.voyager.account.autonomy schema...\n");
29
-
30
-
// Get credentials from environment - use separate vars from agent credentials
31
-
const username = Deno.env.get("SCHEMA_PUBLISHER_USERNAME") || Deno.env.get("BSKY_USERNAME");
32
-
const password = Deno.env.get("SCHEMA_PUBLISHER_PASSWORD") || Deno.env.get("BSKY_APP_PASSWORD");
33
-
const serviceUrl = Deno.env.get("BSKY_SERVICE_URL") || "https://bsky.social";
34
-
const expectedDomain = Deno.env.get("SCHEMA_DOMAIN") || "voyager.studio";
35
-
36
-
if (!username || !password) {
37
-
console.error(
38
-
"β Error: Schema publisher credentials not found.\n"
39
-
);
40
-
console.error(" Set SCHEMA_PUBLISHER_USERNAME and SCHEMA_PUBLISHER_PASSWORD");
41
-
console.error(" OR run with: SCHEMA_PUBLISHER_USERNAME=your.handle SCHEMA_PUBLISHER_PASSWORD=xxxx deno task publish-schema\n");
42
-
console.error(" β οΈ Template users: You do NOT need to run this command!");
43
-
console.error(" The schema is already published by voyager.studio.\n");
44
-
Deno.exit(1);
45
-
}
46
-
47
-
// Initialize agent
48
-
const agent = new AtpAgent({ service: serviceUrl });
49
-
50
-
try {
51
-
// Login
52
-
console.log("π Logging in...");
53
-
await agent.login({
54
-
identifier: username,
55
-
password: password,
56
-
});
57
-
console.log(`β
Logged in as: ${agent.session?.handle} (${agent.session?.did})\n`);
58
-
59
-
// Verify domain ownership
60
-
const handle = agent.session?.handle || "";
61
-
if (!handle.includes(expectedDomain)) {
62
-
console.error(`β Error: This account does not appear to own ${expectedDomain}\n`);
63
-
console.error(` Logged in as: ${handle}`);
64
-
console.error(` Expected domain: ${expectedDomain}\n`);
65
-
console.error(" β οΈ Template users: You do NOT need to publish the schema!");
66
-
console.error(" The schema is already published and discoverable.");
67
-
console.error(" You only create your own autonomy declaration record via 'deno task mount'.\n");
68
-
Deno.exit(1);
69
-
}
70
-
71
-
// Prepare schema record
72
-
const schemaRecord = {
73
-
$type: "com.atproto.lexicon.schema",
74
-
lexicon: AUTONOMY_DECLARATION_LEXICON.lexicon,
75
-
id: AUTONOMY_DECLARATION_LEXICON.id,
76
-
defs: AUTONOMY_DECLARATION_LEXICON.defs,
77
-
description:
78
-
"Lexicon for declaring AI agent autonomy and automation practices for transparency and accountability",
79
-
};
80
-
81
-
console.log(`π Schema Details:`);
82
-
console.log(` NSID: ${schemaRecord.id}`);
83
-
console.log(` Lexicon Version: ${schemaRecord.lexicon}`);
84
-
console.log(` Definitions: ${Object.keys(schemaRecord.defs).join(", ")}\n`);
85
-
86
-
// Check if schema already exists
87
-
let existingSchema = null;
88
-
try {
89
-
const existing = await agent.com.atproto.repo.getRecord({
90
-
repo: agent.session?.did!,
91
-
collection: "com.atproto.lexicon.schema",
92
-
rkey: "studio.voyager.account.autonomy",
93
-
});
94
-
existingSchema = existing.data;
95
-
console.log("π Existing schema found - will update\n");
96
-
} catch (error: any) {
97
-
if (error?.status === 400 || error?.status === 404) {
98
-
console.log("π No existing schema found - will create new\n");
99
-
} else {
100
-
throw error;
101
-
}
102
-
}
103
-
104
-
// Publish schema
105
-
console.log("π€ Publishing schema...");
106
-
const result = await agent.com.atproto.repo.putRecord({
107
-
repo: agent.session?.did!,
108
-
collection: "com.atproto.lexicon.schema",
109
-
rkey: "studio.voyager.account.autonomy",
110
-
record: schemaRecord,
111
-
});
112
-
113
-
console.log(`β
Schema ${existingSchema ? "updated" : "published"} successfully!\n`);
114
-
console.log(`π AT-URI: ${result.data.uri}`);
115
-
console.log(`π CID: ${result.data.cid}\n`);
116
-
117
-
// Verify DNS setup
118
-
console.log("π Next steps:");
119
-
console.log(" 1. Verify DNS TXT record is set:");
120
-
console.log(" Name: _lexicon.account.voyager.studio");
121
-
console.log(" Type: TXT");
122
-
console.log(` Value: did=${agent.session?.did}`);
123
-
console.log(
124
-
"\n 2. Test resolution (may take time for DNS to propagate):",
125
-
);
126
-
console.log(
127
-
` dig TXT _lexicon.account.voyager.studio\n`,
128
-
);
129
-
console.log("β¨ Schema is now discoverable by AT Protocol resolvers!");
130
-
} catch (error) {
131
-
console.error("β Error publishing schema:", error);
132
-
Deno.exit(1);
133
-
}
134
-
};
135
-
136
-
// Run if executed directly
137
-
if (import.meta.main) {
138
-
publishSchema();
139
-
}