a tool to help your Letta AI agents navigate bluesky

Integrate externalServices into agent context and PDS declaration

- Added externalServices field to agentContextObject type
- Created getExternalServices() function to parse EXTERNAL_SERVICES env var
- Validates service names (max 200 chars) and array length (max 20)
- Integrated externalServices into populateAgentContext()
- Updated createAutonomyDeclarationRecord to include externalServices in PDS
- Added externalServices to maintainerContactMemory for agent awareness
- Supports comma-separated list in .env (e.g., "Letta, Railway, Google Gemini 2.5-pro")

Claude a5275450 7c67b553

+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
··· 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…`,
+13
utils/declaration.ts
··· 103 103 const automationLevel = Deno.env.get("AUTOMATION_LEVEL")?.toLowerCase(); 104 104 const projectDescription = Deno.env.get("PROJECT_DESCRIPTION"); 105 105 const disclosureUrl = Deno.env.get("DISCLOSURE_URL"); 106 + const externalServicesEnv = Deno.env.get("EXTERNAL_SERVICES"); 106 107 107 108 const responsiblePartyType = Deno.env.get("RESPONSIBLE_PARTY_TYPE") 108 109 ?.toLowerCase(); ··· 129 130 // Add disclosure URL if provided 130 131 if (disclosureUrl?.trim()) { 131 132 declarationRecord.disclosureUrl = disclosureUrl.trim(); 133 + } 134 + 135 + // Add external services if provided 136 + if (externalServicesEnv?.trim()) { 137 + const services = externalServicesEnv 138 + .split(",") 139 + .map((service) => service.trim()) 140 + .filter((service) => service.length > 0); 141 + 142 + if (services.length > 0) { 143 + declarationRecord.externalServices = services; 144 + } 132 145 } 133 146 134 147 // Build responsible party object if any fields are provided
+1
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 = {