Skip to main content
CopilotKit provides a complete Angular SDK with services, directives, and components to build AI-powered applications. The Angular integration uses dependency injection and follows Angular best practices.

Installation

1

Install the package

Install the Angular package and its peer dependencies:
npm install @copilotkitnext/angular
# Peer dependencies (if not already installed)
npm install @angular/cdk rxjs
2

Import styles

Add CopilotKit styles to your angular.json or import in your global styles:
{
  "styles": [
    "node_modules/@copilotkitnext/angular/styles.css",
    "src/styles.css"
  ]
}
Or in your styles.css:
@import "@copilotkitnext/angular/styles.css";
3

Configure providers

Set up CopilotKit providers in your application configuration:
import { ApplicationConfig } from "@angular/core";
import { provideCopilotKit } from "@copilotkitnext/angular";

export const appConfig: ApplicationConfig = {
  providers: [
    provideCopilotKit({
      runtimeUrl: "http://localhost:3001/api/copilotkit",
    }),
  ],
};

Core Concepts

Configuration Provider

The provideCopilotKit function configures the CopilotKit service with your runtime settings:
import { ApplicationConfig } from "@angular/core";
import {
  provideCopilotKit,
  provideCopilotChatLabels,
} from "@copilotkitnext/angular";

export const appConfig: ApplicationConfig = {
  providers: [
    provideCopilotKit({
      runtimeUrl: "http://localhost:3001/api/copilotkit",
      headers: {
        Authorization: "Bearer your-token",
      },
      licenseKey: "ck_pub_...",
      properties: {
        userId: "user-123",
      },
      frontendTools: [],
      humanInTheLoop: [],
    }),
    provideCopilotChatLabels({
      chatInputPlaceholder: "Ask me anything...",
      chatDisclaimerText: "AI responses may need verification.",
    }),
  ],
};

Configuration Options

  • runtimeUrl - URL of your CopilotKit runtime endpoint
  • headers - Custom headers to include in requests
  • licenseKey - CopilotCloud license key
  • properties - Additional properties to send with requests
  • agents - Local agents (development only)
  • selfManagedAgents - Self-managed agent instances
  • frontendTools - Array of frontend tool configurations
  • humanInTheLoop - Array of human-in-the-loop tool configurations
  • renderToolCalls - Array of tool call render configurations

CopilotKit Service

The CopilotKit service is the core service that manages the connection to your runtime. Inject it into your components or services:
import { Component, inject } from "@angular/core";
import { CopilotKit } from "@copilotkitnext/angular";

@Component({
  selector: "app-my-component",
  template: `
    <div>
      <p>Runtime Status: {{ copilotKit.runtimeConnectionStatus() }}</p>
      <p>Runtime URL: {{ copilotKit.runtimeUrl() }}</p>
    </div>
  `,
})
export class MyComponent {
  copilotKit = inject(CopilotKit);

  ngOnInit() {
    // Access the core CopilotKit instance
    const core = this.copilotKit.core;
    
    // Update runtime configuration
    this.copilotKit.updateRuntime({
      runtimeUrl: "http://new-url/api/copilotkit",
      headers: { "X-Custom": "value" },
    });
  }
}

Frontend Tools

Register frontend tools using the CopilotKit service. Tools can be added at the application level or dynamically in components:
import { Component, inject, Injector } from "@angular/core";
import { CopilotKit } from "@copilotkitnext/angular";
import { z } from "zod";

@Component({
  selector: "app-tool-demo",
  template: `
    <div>
      <button (click)="incrementCounter()">Increment: {{ count }}</button>
    </div>
  `,
})
export class ToolDemoComponent {
  copilotKit = inject(CopilotKit);
  injector = inject(Injector);
  count = 0;

  ngOnInit() {
    // Register a frontend tool
    this.copilotKit.addFrontendTool({
      name: "incrementCounter",
      description: "Increment the counter by a specified amount",
      parameters: z.object({
        amount: z.number().describe("Amount to increment"),
      }),
      handler: (args) => {
        this.count += args.amount;
        return `Counter incremented by ${args.amount}`;
      },
      injector: this.injector,
    });
  }

  ngOnDestroy() {
    // Clean up tool when component is destroyed
    this.copilotKit.removeTool("incrementCounter");
  }

  incrementCounter() {
    this.count++;
  }
}

Tool Call Rendering

Render custom UI for tool executions by creating a component and registering it:
import { Component, input } from "@angular/core";

@Component({
  selector: "app-search-tool-render",
  template: `
    <div class="search-tool-call">
      <h3>Searching for: {{ args().query }}</h3>
      @if (args().limit) {
        <p>Limit: {{ args().limit }} results</p>
      }
      <p>Status: {{ status() }}</p>
    </div>
  `,
  styles: [`
    .search-tool-call {
      padding: 12px;
      border: 1px solid #ccc;
      border-radius: 8px;
      margin: 8px 0;
    }
  `],
})
export class SearchToolRenderComponent {
  name = input.required<string>();
  args = input.required<{ query: string; limit?: number }>();
  status = input.required<string>();
}
Register the renderer in your configuration:
import { ApplicationConfig } from "@angular/core";
import { provideCopilotKit } from "@copilotkitnext/angular";
import { SearchToolRenderComponent } from "./components/search-tool-render";
import { z } from "zod";

export const appConfig: ApplicationConfig = {
  providers: [
    provideCopilotKit({
      runtimeUrl: "http://localhost:3001/api/copilotkit",
      renderToolCalls: [
        {
          name: "search",
          args: z.object({
            query: z.string(),
            limit: z.number().optional(),
          }),
          component: SearchToolRenderComponent,
        },
      ],
    }),
  ],
};
For wildcard rendering (any undefined tool):
@Component({
  selector: "app-wildcard-tool-render",
  template: `
    <div class="unknown-tool">
      <strong>Tool: {{ name() }}</strong>
      <pre>{{ args() | json }}</pre>
      <p>Status: {{ status() }}</p>
    </div>
  `,
})
export class WildcardToolRenderComponent {
  name = input.required<string>();
  args = input.required<any>();
  status = input.required<string>();
}

// In config:
renderToolCalls: [
  {
    name: "*",
    component: WildcardToolRenderComponent,
  } as any,
]

Human-in-the-Loop

Add approval flows to tools using the human-in-the-loop pattern:
import { Component } from "@angular/core";

@Component({
  selector: "app-delete-approval",
  template: `
    <div class="approval-ui">
      <p>Approve deletion of item: {{ args().itemId }}</p>
      <button (click)="approve()">Approve</button>
      <button (click)="reject()">Reject</button>
    </div>
  `,
})
export class DeleteApprovalComponent {
  args = input.required<{ itemId: string }>();
  onApprove = input.required<(result: any) => void>();
  onReject = input.required<(reason: string) => void>();

  approve() {
    this.onApprove()({ success: true });
  }

  reject() {
    this.onReject()("User rejected deletion");
  }
}
Register in configuration:
import { z } from "zod";

provideCopilotKit({
  runtimeUrl: "http://localhost:3001/api/copilotkit",
  humanInTheLoop: [
    {
      name: "deleteItem",
      description: "Delete an item (requires approval)",
      parameters: z.object({
        itemId: z.string(),
      }),
      component: DeleteApprovalComponent,
    },
  ],
})

Chat Components

CopilotChat

The main chat interface component:
import { Component } from "@angular/core";
import { CopilotChat } from "@copilotkitnext/angular";

@Component({
  selector: "app-chat",
  standalone: true,
  imports: [CopilotChat],
  template: `
    <div style="height: 100vh;">
      <copilot-chat [threadId]="'thread-123'"></copilot-chat>
    </div>
  `,
})
export class ChatComponent {}

CopilotChatView

A lower-level chat view component with more customization options:
import { Component } from "@angular/core";
import { CopilotChatView } from "@copilotkitnext/angular";

@Component({
  selector: "app-chat-view",
  standalone: true,
  imports: [CopilotChatView],
  template: `
    <copilot-chat-view
      [threadId]="threadId"
      [agentId]="agentId"
      [className]="'custom-chat-class'"
    ></copilot-chat-view>
  `,
})
export class ChatViewComponent {
  threadId = "my-thread";
  agentId = "my-agent";
}

Directives

copilotKitAgentContext

Provide dynamic context to your agent using the directive:
import { Component } from "@angular/core";
import { CopilotKitAgentContextDirective } from "@copilotkitnext/angular";

@Component({
  selector: "app-context-demo",
  standalone: true,
  imports: [CopilotKitAgentContextDirective],
  template: `
    <div
      [copilotKitAgentContext]="{
        description: 'Current user information',
        value: currentUser
      }"
    >
      <p>Logged in as: {{ currentUser.name }}</p>
    </div>
  `,
})
export class ContextDemoComponent {
  currentUser = {
    id: "user-123",
    name: "John Doe",
    email: "[email protected]",
  };
}

Complete Example

Here’s a full example of a standalone Angular component with CopilotKit:
import { Component, inject, Injector } from "@angular/core";
import { CommonModule } from "@angular/common";
import {
  CopilotChat,
  CopilotKit,
  CopilotKitAgentContextDirective,
} from "@copilotkitnext/angular";
import { z } from "zod";

@Component({
  selector: "app-counter-chat",
  standalone: true,
  imports: [
    CommonModule,
    CopilotChat,
    CopilotKitAgentContextDirective,
  ],
  template: `
    <div style="display: flex; height: 100vh;">
      <div
        style="flex: 1; padding: 20px;"
        [copilotKitAgentContext]="{
          description: 'Current counter value',
          value: count
        }"
      >
        <h1>Counter: {{ count }}</h1>
        <button (click)="increment()">Increment</button>
        <button (click)="reset()">Reset</button>
      </div>
      
      <div style="flex: 1;">
        <copilot-chat [threadId]="'counter-thread'"></copilot-chat>
      </div>
    </div>
  `,
})
export class CounterChatComponent {
  copilotKit = inject(CopilotKit);
  injector = inject(Injector);
  count = 0;

  ngOnInit() {
    // Register increment tool
    this.copilotKit.addFrontendTool({
      name: "incrementCounter",
      description: "Increment the counter by a specified amount",
      parameters: z.object({
        amount: z.number().describe("Amount to increment"),
      }),
      handler: (args) => {
        this.count += args.amount;
        return `Counter incremented by ${args.amount}. New value: ${this.count}`;
      },
      injector: this.injector,
    });

    // Register reset tool
    this.copilotKit.addFrontendTool({
      name: "resetCounter",
      description: "Reset the counter to zero",
      parameters: z.object({}),
      handler: () => {
        this.count = 0;
        return "Counter reset to 0";
      },
      injector: this.injector,
    });
  }

  ngOnDestroy() {
    this.copilotKit.removeTool("incrementCounter");
    this.copilotKit.removeTool("resetCounter");
  }

  increment() {
    this.count++;
  }

  reset() {
    this.count = 0;
  }
}

Reactive Programming with RxJS

The CopilotKit service uses Angular Signals, but you can convert them to Observables when needed:
import { Component, inject } from "@angular/core";
import { toObservable } from "@angular/core/rxjs-interop";
import { CopilotKit } from "@copilotkitnext/angular";

@Component({
  selector: "app-reactive-demo",
  template: `<div>Status: {{ status$ | async }}</div>`,
})
export class ReactiveDemoComponent {
  copilotKit = inject(CopilotKit);
  
  status$ = toObservable(this.copilotKit.runtimeConnectionStatus);
  
  ngOnInit() {
    this.status$.subscribe(status => {
      console.log("Connection status changed:", status);
    });
  }
}

TypeScript Support

CopilotKit Angular is fully typed. Import types for custom implementations:
import type {
  CopilotKitConfig,
  FrontendToolConfig,
  HumanInTheLoopConfig,
  RenderToolCallConfig,
} from "@copilotkitnext/angular";

Next Steps

Human-in-the-Loop

Learn how to add approval flows to your tools

Tool Development

Build custom tools for your agents

Agent Configuration

Configure and customize your agents

Build docs developers (and LLMs) love