Overview
The CopilotKit service is a root-level Angular service that manages agents, runtime connections, and tool configurations. It provides reactive signals for state management and methods for dynamic configuration updates.
Usage
import { Component, inject } from '@angular/core';
import { CopilotKit } from '@copilotkit/angular';
@Component({
selector: 'app-chat',
template: `
<div>
Status: {{ copilotKit.runtimeConnectionStatus() }}
Agents: {{ copilotKit.agents() | json }}
</div>
`
})
export class ChatComponent {
copilotKit = inject(CopilotKit);
}
Class Definition
@Injectable({ providedIn: 'root' })
class CopilotKit {
// Readonly signals
readonly agents: Signal<Record<string, AbstractAgent>>;
readonly runtimeConnectionStatus: Signal<CopilotKitCoreRuntimeConnectionStatus>;
readonly runtimeUrl: Signal<string | undefined>;
readonly runtimeTransport: Signal<CopilotRuntimeTransport>;
readonly headers: Signal<Record<string, string>>;
// Core instance
readonly core: CopilotKitCore;
// Configuration signals
readonly toolCallRenderConfigs: Signal<RenderToolCallConfig[]>;
readonly clientToolCallRenderConfigs: Signal<FrontendToolConfig[]>;
readonly humanInTheLoopToolRenderConfigs: Signal<HumanInTheLoopConfig[]>;
}
Properties
agents
readonly agents: Signal<Record<string, AbstractAgent>>
A reactive signal containing all available agents, indexed by agent ID.
Example:
const copilotKit = inject(CopilotKit);
effect(() => {
const agents = copilotKit.agents();
console.log('Available agents:', Object.keys(agents));
});
runtimeConnectionStatus
readonly runtimeConnectionStatus: Signal<CopilotKitCoreRuntimeConnectionStatus>
Current connection status to the runtime server.
Possible values:
CopilotKitCoreRuntimeConnectionStatus.Disconnected
CopilotKitCoreRuntimeConnectionStatus.Connecting
CopilotKitCoreRuntimeConnectionStatus.Connected
Example:
const copilotKit = inject(CopilotKit);
const status = copilotKit.runtimeConnectionStatus();
if (status === CopilotKitCoreRuntimeConnectionStatus.Connected) {
console.log('Runtime is ready');
}
runtimeUrl
readonly runtimeUrl: Signal<string | undefined>
Current runtime server URL.
runtimeTransport
readonly runtimeTransport: Signal<CopilotRuntimeTransport>
Transport protocol used for runtime communication ('rest' or 'sse').
readonly headers: Signal<Record<string, string>>
Current HTTP headers sent with runtime requests.
core
readonly core: CopilotKitCore
The underlying CopilotKitCore instance. Provides low-level access to the core functionality.
Methods
Add a frontend tool that executes in the browser.
addFrontendTool(
clientToolWithInjector: FrontendToolConfig & { injector: Injector }
): void
clientToolWithInjector
FrontendToolConfig & { injector: Injector }
Tool configuration with Angular injector for dependency injection support.
Example:
import { Component, inject, Injector } from '@angular/core';
import { CopilotKit } from '@copilotkit/angular';
import { z } from 'zod';
@Component({ /* ... */ })
export class MyComponent {
private copilotKit = inject(CopilotKit);
private injector = inject(Injector);
private userService = inject(UserService);
ngOnInit() {
this.copilotKit.addFrontendTool({
name: 'getUserProfile',
description: 'Get user profile information',
parameters: z.object({
userId: z.string()
}),
handler: async ({ userId }) => {
// Can use injected services
return this.userService.getProfile(userId);
},
injector: this.injector
});
}
}
Register a custom component to render tool calls in the UI.
addRenderToolCall(renderConfig: RenderToolCallConfig): void
Configuration specifying which tool to render and with which component.
Example:
import { Component, inject } from '@angular/core';
import { CopilotKit } from '@copilotkit/angular';
import { z } from 'zod';
import { WeatherDisplayComponent } from './weather-display.component';
@Component({ /* ... */ })
export class MyComponent {
private copilotKit = inject(CopilotKit);
ngOnInit() {
this.copilotKit.addRenderToolCall({
name: 'getWeather',
args: z.object({
location: z.string()
}),
component: WeatherDisplayComponent,
agentId: 'weather-agent' // optional
});
}
}
addHumanInTheLoop()
Add a tool that requires human approval before execution.
addHumanInTheLoop(humanInTheLoopTool: HumanInTheLoopConfig): void
Tool configuration for human-in-the-loop approval.
Example:
this.copilotKit.addHumanInTheLoop({
name: 'deleteDatabase',
description: 'Delete the entire database (requires approval)',
parameters: z.object({
confirmationCode: z.string()
})
});
Remove a previously registered tool.
removeTool(toolName: string, agentId?: string): void
Name of the tool to remove.
Optional agent ID. If provided, only removes the tool from that specific agent.
Example:
// Remove tool from all agents
this.copilotKit.removeTool('getUserProfile');
// Remove tool from specific agent
this.copilotKit.removeTool('getUserProfile', 'customer-service-agent');
getAgent()
Retrieve a specific agent by ID.
getAgent(agentId: string): AbstractAgent | undefined
Returns: The agent instance or undefined if not found.
Example:
const agent = this.copilotKit.getAgent('my-agent');
if (agent) {
console.log('Agent found:', agent);
}
updateRuntime()
Update runtime configuration dynamically.
updateRuntime(options: {
runtimeUrl?: string;
runtimeTransport?: CopilotRuntimeTransport;
headers?: Record<string, string>;
properties?: Record<string, unknown>;
agents?: Record<string, AbstractAgent>;
selfManagedAgents?: Record<string, AbstractAgent>;
}): void
Transport protocol to use.
options.agents
Record<string, AbstractAgent>
New agent map.
options.selfManagedAgents
Record<string, AbstractAgent>
New self-managed agent map.
Example:
// Update authentication headers
this.copilotKit.updateRuntime({
headers: {
'Authorization': `Bearer ${newToken}`
}
});
// Switch to a different runtime
this.copilotKit.updateRuntime({
runtimeUrl: 'https://new-runtime.example.com/api',
runtimeTransport: 'sse'
});
// Add/update agents dynamically
this.copilotKit.updateRuntime({
agents: {
'new-agent': new BuiltInAgent({
model: 'openai/gpt-4o',
apiKey: process.env.OPENAI_API_KEY
})
}
});
Agent Store
To work with a specific agent and its messages/state, use the injectAgentStore() helper:
import { Component, computed, inject } from '@angular/core';
import { injectAgentStore } from '@copilotkit/angular';
@Component({
selector: 'app-chat',
template: `
<div>
@for (message of agentStore().messages(); track message.id) {
<div>{{ message.content }}</div>
}
@if (agentStore().isRunning()) {
<div>Agent is thinking...</div>
}
</div>
`
})
export class ChatComponent {
agentStore = injectAgentStore('my-agent');
// Or with dynamic agent ID:
// agentId = signal('my-agent');
// agentStore = injectAgentStore(this.agentId);
}
AgentStore Interface
class AgentStore {
readonly agent: AbstractAgent;
readonly isRunning: Signal<boolean>;
readonly messages: Signal<Message[]>;
readonly state: Signal<any>;
}
Examples
Monitor Connection Status
import { Component, inject, effect } from '@angular/core';
import { CopilotKit, CopilotKitCoreRuntimeConnectionStatus } from '@copilotkit/angular';
@Component({
selector: 'app-status',
template: `
<div [class]="statusClass()">
{{ statusText() }}
</div>
`
})
export class StatusComponent {
copilotKit = inject(CopilotKit);
statusText = computed(() => {
const status = this.copilotKit.runtimeConnectionStatus();
switch (status) {
case CopilotKitCoreRuntimeConnectionStatus.Connected:
return 'Connected';
case CopilotKitCoreRuntimeConnectionStatus.Connecting:
return 'Connecting...';
default:
return 'Disconnected';
}
});
statusClass = computed(() => {
const status = this.copilotKit.runtimeConnectionStatus();
return status === CopilotKitCoreRuntimeConnectionStatus.Connected
? 'text-green-600'
: 'text-gray-400';
});
}
import { Component, inject, Injector } from '@angular/core';
import { CopilotKit } from '@copilotkit/angular';
import { z } from 'zod';
@Component({ /* ... */ })
export class DynamicToolsComponent {
private copilotKit = inject(CopilotKit);
private injector = inject(Injector);
registerSearchTool() {
this.copilotKit.addFrontendTool({
name: 'searchDatabase',
description: 'Search the database',
parameters: z.object({
query: z.string(),
limit: z.number().optional()
}),
handler: async ({ query, limit = 10 }) => {
const response = await fetch(`/api/search?q=${query}&limit=${limit}`);
return response.json();
},
injector: this.injector
});
}
unregisterSearchTool() {
this.copilotKit.removeTool('searchDatabase');
}
}
import { Component, inject, effect } from '@angular/core';
import { CopilotKit } from '@copilotkit/angular';
import { AuthService } from './auth.service';
@Component({ /* ... */ })
export class AppComponent {
private copilotKit = inject(CopilotKit);
private authService = inject(AuthService);
constructor() {
// Update headers when auth token changes
effect(() => {
const token = this.authService.token();
if (token) {
this.copilotKit.updateRuntime({
headers: {
'Authorization': `Bearer ${token}`
}
});
}
});
}
}
See Also