Skip to content

@memberjunction/ng-agent-client

Thin Angular wrapper around @memberjunction/ai-agent-client. Provides Angular dependency injection and automatic lifecycle cleanup — nothing more.

  • AgentClientService — An @Injectable({ providedIn: 'root' }) singleton that owns an AgentClientSession internally.
  • Pass-through API — Every public method and observable on AgentClientSession is exposed directly. No transformation, no added logic.
  • Lifecycle management — Calls session.Dispose() in ngOnDestroy to prevent memory leaks.
  • No business logic
  • No tool handlers — the consuming application registers tools
  • No GraphQL code — that lives in the core SDK
  • No WebSocket code — removed; transport is handled by GraphQLDataProvider
import { Component, inject, OnInit, OnDestroy } from '@angular/core';
import { AgentClientService } from '@memberjunction/ng-agent-client';
import { Subject, takeUntil } from 'rxjs';
@Component({ ... })
export class MyChatComponent implements OnInit, OnDestroy {
private agentClient = inject(AgentClientService);
private destroy$ = new Subject<void>();
ngOnInit(): void {
// Register tools
this.agentClient.RegisterTool({
Name: 'NavigateToRecord',
Description: 'Open an entity record',
ParameterSchema: { type: 'object', properties: { EntityName: { type: 'string' } } },
Handler: async (params) => {
// app-specific logic
return { Success: true, Data: 'done' };
},
});
// Listen for events
this.agentClient.ToolRequested$
.pipe(takeUntil(this.destroy$))
.subscribe(event => console.log('Tool requested:', event.Request.ToolName));
// Start session
this.agentClient.StartSession('session-id');
}
async SendMessage(text: string): Promise<void> {
const result = await this.agentClient.RunAgent({
AgentId: 'agent-uuid',
Messages: [{ role: 'user', content: text }],
});
console.log('Agent result:', result.Success);
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
// AgentClientService.ngOnDestroy() calls session.Dispose() automatically
}
}

All methods and observables mirror AgentClientSession from the core SDK:

MemberTypeDescription
ToolRequested$ObservableEmitted before tool execution
ToolExecuted$ObservableEmitted after tool execution
AgentProgress$ObservableAgent progress updates
SessionActive$ObservableSession state changes
Error$ObservableErrors during communication or execution
SessionIdstring | nullCurrent session ID
IsActivebooleanWhether a session is active
RegisterTool(tool)methodRegister a client-side tool handler
UnregisterTool(name)methodRemove a tool
GetRegisteredTools()methodList all registered tools
StartSession(id)methodStart listening for tool requests
StopSession()methodStop and clean up
RunAgent(params)methodExecute an agent
RunAgentFromConversationDetail(params)methodExecute from conversation detail

This Angular wrapper is a convenience, not a requirement. The core SDK (@memberjunction/ai-agent-client) already provides RxJS observables and requires no Angular-specific APIs. If you run into issues with Angular’s providedIn: 'root' singleton pattern — such as duplicate instances from multiple module imports or npm hoisting conflicts — you can use AgentClientSession directly:

import { AgentClientSession } from '@memberjunction/ai-agent-client';
// Create and manage the session yourself
const session = new AgentClientSession();
session.RegisterTool({ Name: 'MyTool', ... });
session.StartSession('session-id');
// Same observables, same API — no Angular DI involved
session.ToolRequested$.subscribe(event => { ... });
await session.RunAgent({ AgentId: 'sage-id', Messages: [...] });
// Clean up when done
session.Dispose();

This is particularly useful in non-standard Angular setups (micro-frontends, lazy-loaded feature modules with their own injectors, or hybrid apps).