From 4b2ee37ec2a1df1de1a91e845fcc74651c109c64 Mon Sep 17 00:00:00 2001 From: Muazzam Kazmi Date: Mon, 6 Apr 2026 22:28:57 +0500 Subject: [PATCH 1/2] fix anthropic provider error --- src/runtime/modules/ai.ts | 10 ++++- test/runtime/llm-service.test.ts | 66 +++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/runtime/modules/ai.ts b/src/runtime/modules/ai.ts index dae0fe97..c530d0ac 100644 --- a/src/runtime/modules/ai.ts +++ b/src/runtime/modules/ai.ts @@ -1298,14 +1298,20 @@ export async function findAgentByName(name: string, env: Environment): Promise { + // LLM rows are upserted during startup via runStandaloneStatements on GlobalEnvironment. + // Agent invocations often run under a child env (e.g. exec-graph sets active user from the + // event). Querying with that env can use a different tenant than bootstrap, so the LLM row + // is invisible. Use a child of GlobalEnvironment so lookup matches inserted configuration. + const lookupEnv = new Environment('llm-provider-lookup', GlobalEnvironment); + let p: AgentServiceProvider | undefined = ProviderDb.get(llmName); if (p === undefined) { const result: Instance[] = await parseAndEvaluateStatement( `{${CoreAIModuleName}/${LlmEntityName} {name? "${llmName}"}}`, undefined, - env + lookupEnv ); if (result.length > 0) { const llm: Instance = result[0]; diff --git a/test/runtime/llm-service.test.ts b/test/runtime/llm-service.test.ts index f6324927..d4a7a133 100644 --- a/test/runtime/llm-service.test.ts +++ b/test/runtime/llm-service.test.ts @@ -1,7 +1,8 @@ import { beforeAll, describe, expect, test } from 'vitest'; import { doInternModule } from '../util.js'; -import { GlobalEnvironment, parseAndEvaluateStatement } from '../../src/runtime/interpreter.js'; +import { Environment, GlobalEnvironment, parseAndEvaluateStatement } from '../../src/runtime/interpreter.js'; import { setLocalEnv } from '../../src/runtime/auth/defs.js'; +import { findProviderForLLM } from '../../src/runtime/modules/ai.js'; describe('LLM Service Selection', () => { beforeAll(() => { @@ -207,4 +208,67 @@ describe('LLM Service Selection', () => { const config = llm.lookup('config'); expect(config.get ? config.get('model') : config['model']).toBe('claude-3-sonnet-20241022'); }); + + test('named LLM + @public myHelloAgent: provider resolve and live invoke when API key is set', async () => { + const envKey = process.env.AGENTLANG_ANTHROPIC_KEY; + const useLiveAnthropic = Boolean( + envKey && envKey !== 'test-anthropic-key' && envKey.length > 12 + ); + if (useLiveAnthropic) { + setLocalEnv('AGENTLANG_ANTHROPIC_KEY', envKey!); + } + + await doInternModule( + 'TestClaudeNamedLLM', + ` + {agentlang.ai/LLM { + name "claude", + service "anthropic", + config { + "model": "claude-sonnet-4-20250514", + "max_tokens": 4096, + "stream": false + } + }, @upsert} + + @public agent myHelloAgent { + llm "claude", + role "You are to greet me with hello" + } + ` + ); + + const childEnv = new Environment('jwt-like-child', GlobalEnvironment); + childEnv.setActiveUser('some-end-user-id'); + + const provider = await findProviderForLLM('claude', childEnv); + expect(provider).toBeDefined(); + + if (useLiveAnthropic) { + const response = await parseAndEvaluateStatement( + `{TestClaudeNamedLLM/myHelloAgent {message "Please greet me in one short sentence."}}`, + undefined, + GlobalEnvironment + ); + expect(typeof response).toBe('string'); + expect((response as string).length).toBeGreaterThan(0); + expect((response as string).toLowerCase()).toMatch(/hello|hi|hey/); + } + }); + + test('findProviderForLLM fails clearly when LLM entity was never upserted', async () => { + await doInternModule( + 'TestMissingLLMRow', + ` + @public agent orphanAgent { + llm "no_such_llm_registered", + instruction "test" + } + ` + ); + + await expect(findProviderForLLM('no_such_llm_registered', GlobalEnvironment)).rejects.toThrow( + /no agentlang\.ai\/LLM row/ + ); + }); }); From 661118245af2313735d8ed3f1f793b08e456ba76 Mon Sep 17 00:00:00 2001 From: Muazzam Kazmi Date: Mon, 6 Apr 2026 22:40:28 +0500 Subject: [PATCH 2/2] fix assertion --- src/runtime/modules/ai.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runtime/modules/ai.ts b/src/runtime/modules/ai.ts index c530d0ac..91cc5071 100644 --- a/src/runtime/modules/ai.ts +++ b/src/runtime/modules/ai.ts @@ -1330,7 +1330,10 @@ export async function findProviderForLLM( if (p) { return p; } else { - throw new Error(`Failed to load provider for ${llmName}`); + throw new Error( + `Failed to load provider for ${llmName}: no agentlang.ai/LLM row named "${llmName}". ` + + `Define it with {agentlang.ai/LLM { name "${llmName}", service "openai"|"anthropic", ... }, @upsert} in a loaded module (not config.al, which is excluded from automatic loading), or add it under agentlang.ai in agentlang config JSON.` + ); } }