diff --git a/src/core/bot.ts b/src/core/bot.ts index 1b9396b..3303d9d 100644 --- a/src/core/bot.ts +++ b/src/core/bot.ts @@ -950,6 +950,7 @@ export class LettaBot implements AgentSession { const newAgentId = await createAgent({ systemPrompt: SYSTEM_PROMPT, memory: loadMemoryBlocks(this.config.agentName), + tags: ['origin:lettabot'], ...(this.config.memfs !== undefined ? { memfs: this.config.memfs } : {}), }); const currentBaseUrl = process.env.LETTA_BASE_URL || 'https://api.letta.com'; diff --git a/src/core/sdk-session-contract.test.ts b/src/core/sdk-session-contract.test.ts index 49bf5ee..7ef8ddb 100644 --- a/src/core/sdk-session-contract.test.ts +++ b/src/core/sdk-session-contract.test.ts @@ -20,7 +20,22 @@ vi.mock('../tools/letta-api.js', () => ({ getLatestRunError: vi.fn().mockResolvedValue(null), })); -import { createSession, resumeSession } from '@letta-ai/letta-code-sdk'; +vi.mock('../skills/loader.js', () => ({ + installSkillsToAgent: vi.fn(), + withAgentSkillsOnPath: vi.fn((_id: string, fn: () => unknown) => fn()), + getAgentSkillExecutableDirs: vi.fn().mockReturnValue([]), + isVoiceMemoConfigured: vi.fn().mockReturnValue(false), +})); + +vi.mock('./memory.js', () => ({ + loadMemoryBlocks: vi.fn().mockReturnValue([]), +})); + +vi.mock('./system-prompt.js', () => ({ + SYSTEM_PROMPT: 'test system prompt', +})); + +import { createAgent, createSession, resumeSession } from '@letta-ai/letta-code-sdk'; import { getLatestRunError } from '../tools/letta-api.js'; import { LettaBot } from './bot.js'; @@ -448,4 +463,40 @@ describe('SDK session contract', () => { 'Agent run failed: timeout' ); }); + + it('passes tags: [origin:lettabot] to createAgent when creating a new agent', async () => { + delete process.env.LETTA_AGENT_ID; + + vi.mocked(createAgent).mockResolvedValue('agent-new-tagged'); + + const mockSession = { + initialize: vi.fn(async () => undefined), + send: vi.fn(async (_message: unknown) => undefined), + stream: vi.fn(() => + (async function* () { + yield { type: 'assistant', content: 'hello' }; + yield { type: 'result', success: true }; + })() + ), + close: vi.fn(() => undefined), + agentId: 'agent-new-tagged', + conversationId: 'conversation-new-tagged', + }; + + vi.mocked(createSession).mockReturnValue(mockSession as never); + + const bot = new LettaBot({ + workingDir: join(dataDir, 'working'), + allowedTools: [], + }); + + await bot.sendToAgent('first message'); + + expect(vi.mocked(createAgent)).toHaveBeenCalledTimes(1); + expect(vi.mocked(createAgent)).toHaveBeenCalledWith( + expect.objectContaining({ + tags: ['origin:lettabot'], + }) + ); + }); }); diff --git a/src/onboard.ts b/src/onboard.ts index e04be52..504a074 100644 --- a/src/onboard.ts +++ b/src/onboard.ts @@ -1538,6 +1538,7 @@ export async function onboard(options?: { nonInteractive?: boolean }): Promise