+1
.env.example
+1
.env.example
+1
README.md
+1
README.md
···
52
52
- **`AUTOMATION_DESCRIPTION`**: a description of what your agent generally does on bluesky.
53
53
- **`DISCLOSURE_URL`**: a URL to a disclosure document of some kind, likely a longer version of your `AUTOMATION_DESCRIPTION`.
54
54
- **`RESPONSIBLE_PARTY_BSKY`**: the DID or bluesky handle of the responsible party
55
+
- **`EXTERNAL_SERVICES`**: a comma-separated list of external tools and services your agent relies on outside of Bluesky (e.g., "Letta, Railway, Google Gemini 2.5-pro"). This information is added to your agent's autonomy declaration record on the PDS and included in the agent's memory for transparency.
55
56
- **`PRESERVE_MEMORY_BLOCKS`**: a boolean for controlling if your agent's memory blocks can be overridden if you run `deno task mount` more than once. Setting this value to **`true`** will allow your agent's version of those memory blocks to persist if they already exist. This is false by default.
+9
memories/maintainerContact.ts
+9
memories/maintainerContact.ts
···
45
45
: ""
46
46
}
47
47
48
+
${
49
+
agentContext.externalServices && agentContext.externalServices.length > 0
50
+
? `
51
+
**External Services I Rely On:**
52
+
${agentContext.externalServices.map((service) => `- ${service}`).join("\n")}
53
+
`
54
+
: ""
55
+
}
56
+
48
57
**When to share this information:**
49
58
50
59
- **Sharing this information should be exceedingly rare.** This exists so my maintainer remains accountable for my behavior, not as information to share casually.
+41
utils/agentContext.ts
+41
utils/agentContext.ts
···
501
501
);
502
502
};
503
503
504
+
export const getExternalServices = (): string[] | undefined => {
505
+
const value = Deno.env.get("EXTERNAL_SERVICES")?.trim();
506
+
507
+
if (!value?.length) {
508
+
return undefined;
509
+
}
510
+
511
+
// Parse comma-separated list
512
+
const services = value
513
+
.split(",")
514
+
.map((service) => service.trim())
515
+
.filter((service) => service.length > 0);
516
+
517
+
if (services.length === 0) {
518
+
return undefined;
519
+
}
520
+
521
+
// Validate each service string
522
+
for (const service of services) {
523
+
if (service.length > 200) {
524
+
throw Error(
525
+
`External service name too long: "${service.substring(0, 50)}..." (max 200 characters)`,
526
+
);
527
+
}
528
+
}
529
+
530
+
// Validate array length
531
+
if (services.length > 20) {
532
+
throw Error(
533
+
`Too many external services specified: ${services.length} (max 20)`,
534
+
);
535
+
}
536
+
537
+
return services;
538
+
};
539
+
504
540
const populateAgentContext = async (): Promise<agentContextObject> => {
505
541
console.log("building new agentContext object…");
506
542
const context: agentContextObject = {
···
559
595
const responsiblePartyBsky = await getResponsiblePartyBsky();
560
596
if (responsiblePartyBsky) {
561
597
context.responsiblePartyBsky = responsiblePartyBsky;
598
+
}
599
+
600
+
const externalServices = getExternalServices();
601
+
if (externalServices) {
602
+
context.externalServices = externalServices;
562
603
}
563
604
console.log(
564
605
`\`agentContext\` object built for ${context.agentBskyName}, BEGIN TASK…`,
+16
utils/declaration.ts
+16
utils/declaration.ts
···
1
1
import { bsky } from "../utils/bsky.ts";
2
2
import type { AutonomyDeclarationRecord } from "./types.ts";
3
3
import { Lexicons } from "@atproto/lexicon";
4
+
import { agentContext } from "./agentContext.ts";
4
5
5
6
export const AUTONOMY_DECLARATION_LEXICON = {
6
7
"lexicon": 1,
···
73
74
"description":
74
75
"URL with additional information about this account's automation",
75
76
},
77
+
"externalServices": {
78
+
"type": "array",
79
+
"items": {
80
+
"type": "string",
81
+
"maxLength": 200,
82
+
},
83
+
"maxLength": 20,
84
+
"description":
85
+
"External tools and services this agent relies on outside of Bluesky (e.g., 'Letta', 'Railway', 'Google Gemini 2.5-pro')",
86
+
},
76
87
"createdAt": {
77
88
"type": "string",
78
89
"format": "datetime",
···
119
130
// Add disclosure URL if provided
120
131
if (disclosureUrl?.trim()) {
121
132
declarationRecord.disclosureUrl = disclosureUrl.trim();
133
+
}
134
+
135
+
// Add external services from agentContext (already parsed and validated)
136
+
if (agentContext.externalServices) {
137
+
declarationRecord.externalServices = agentContext.externalServices;
122
138
}
123
139
124
140
// Build responsible party object if any fields are provided
+4
utils/types.ts
+4
utils/types.ts
···
64
64
automationDescription?: string; // short description of what this agent does
65
65
disclosureUrl?: string; // url to a ToS/Privacy Policy style page
66
66
responsiblePartyBsky?: string; // handle w/o @ or DID of responsible party
67
+
externalServices?: string[]; // external tools/services this agent relies on
67
68
};
68
69
69
70
export type AutonomyDeclarationRecord = {
···
88
89
89
90
// Where can someone learn more?
90
91
disclosureUrl?: string; // URI format
92
+
93
+
// What external tools/services does this agent rely on?
94
+
externalServices?: string[]; // e.g., ["Letta", "Railway", "Google Gemini 2.5-pro"]
91
95
92
96
// When was this declaration created?
93
97
createdAt: string; // ISO datetime (required)