# Angular quickstart

Add a Web Agent to an Angular app. At the end, the agent's launcher is on every page of your app and the agent knows which user is signed in.

## Prerequisites

- An Angular 19 or later app with standalone components, started with `bootstrapApplication`.
- A Web Agent in your workspace whose analysis has finished, with a version deployed to Production.

## 1. Copy your agent ID

1. In the portal, go to [**Web Agents**](https://auth.faustine.ai/go?to=%2Fweb-assistants) and select your agent.
2. In the **Overview** tab, find the **Install the assistant** card and select the **npm** tab.
3. Copy the `agentId` value from the snippet.

## 2. Install the loader

**npm**

```bash
npm install @faustine-ai/web-agent
```

**pnpm**

```bash
pnpm add @faustine-ai/web-agent
```

**yarn**

```bash
yarn add @faustine-ai/web-agent
```

**bun**

```bash
bun add @faustine-ai/web-agent
```

The package is plain JavaScript with its own types. It loads the widget and your agent's served version from Faustine when the page loads.

## 3. Start the agent

Wrap the loader in a service, so that the rest of the app reaches the agent through dependency injection.

```ts filename="src/app/faustine.service.ts"
import { Injectable } from '@angular/core';
import Faustine, { type AgentHandle, type IdentifyInfo } from '@faustine-ai/web-agent';

@Injectable({ providedIn: 'root' })
export class FaustineService {
  private agent: AgentHandle | null = null;

  start(): void {
    this.agent ??= Faustine.init({ agentId: '<AGENT_ID>' });
  }

  identify(info: IdentifyInfo): void {
    this.agent?.identify(info);
  }

  logout(): void {
    this.agent?.logout();
  }
}
```

Start the agent from an app initializer in `app.config.ts`. The initializer runs once, before the root component renders.

```ts filename="src/app/app.config.ts"
import { ApplicationConfig, inject, provideAppInitializer } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { FaustineService } from './faustine.service';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideAppInitializer(() => inject(FaustineService).start()),
  ],
};
```

`init` returns immediately and loads the widget in the background, so the initializer does not delay the app. It loads the Production environment. To load another one, pass its name: `env: 'Staging'`.

## 4. Identify the signed-in user

In the root component, an effect tells the agent when the user changes. This example passes a display name and email, which appear in the agent's **Monitoring** tab as **Unverified**.

```ts filename="src/app/app.ts"
import { Component, effect, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { FaustineService } from './faustine.service';
import { SessionService } from './session.service';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet],
  template: '<router-outlet />',
})
export class App {
  private readonly faustine = inject(FaustineService);
  private readonly session = inject(SessionService);
  private signedIn = false;

  constructor() {
    effect(() => {
      const user = this.session.user();
      if (user) {
        this.faustine.identify({ userId: user.id, name: user.name, email: user.email });
        this.signedIn = true;
      } else if (this.signedIn) {
        this.faustine.logout();
        this.signedIn = false;
      }
    });
  }
}
```

`SessionService` stands for your own service, and `user` is a signal that holds the signed-in user or `null`. The effect calls `logout` only after a user has been identified, so a visitor who never signs in keeps their conversation.

If your session is an observable, subscribe to it instead and run the same two branches, or convert it with `toSignal`.

For production, replace the labels with a token signed by your backend. See [Verify your users with a signed token](https://docs.faustine.ai/web-agents/verify-users/).

## 5. Run your app

```bash
ng serve
```

> **Checkpoint:** The agent's launcher appears on the page. Select it and send a message. In the portal, the conversation appears under the agent's **Monitoring** tab.

## Install with a coding agent

The `install-faustine` skill does steps 2 to 4 in your repository and follows its conventions.

```bash
npx skills add faustine-ai/skills
```

Then, in your coding agent:

```text
/install-faustine <AGENT_ID>
```

## Install without a build step

If you cannot add a dependency, load the widget from a script tag in `src/index.html`. The **JS / Auto** tab of the **Install the assistant** card has this snippet with your ID filled in.

```html filename="src/index.html"
<script src="https://webagent.faustine.ai/embed?wid=<AGENT_ID>" async></script>
```

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| No launcher, and the request to `webagent.faustine.ai/embed` returns `404` | No environment of the agent serves a version. | [Publish a version](https://docs.faustine.ai/web-agents/publish-a-version/). |
| No launcher, and the same request returns `403` | The page's domain is not in the environment's allowed domains. `ng serve` runs on `localhost:4200`. | Add `localhost:4200` to the environment you develop against. See [Restrict the domains that can load the agent](https://docs.faustine.ai/web-agents/restrict-domains/). |
| `provideAppInitializer` is not exported | The app is on Angular 18 or earlier. | Call `inject(FaustineService).start()` in the constructor of the root component. |
| The server log shows `init called outside a browser` | The app renders on the server and the initializer ran there. `init` does nothing on the server. | No change is needed. The agent starts when the app loads in the browser. |

## Next steps

- [Verify your users with a signed token](https://docs.faustine.ai/web-agents/verify-users/): give users their history on every device.
- [Restrict the domains that can load the agent](https://docs.faustine.ai/web-agents/restrict-domains/): allow your own domains only.
- [Use your own launcher button](https://docs.faustine.ai/web-agents/custom-launcher/): open the agent from a button in your layout.
- [JavaScript API](https://docs.faustine.ai/reference/javascript-api/): every option of `init` and every method of the handle.
