# Chat Participants

> Create multi-turn chats or simulate conversations with multiple chat participants

The `defChatParticipant` allows to register a function that can add new user messages in the chat sequence, …or rewrite the entire message history. This allows to create multi-turn chat, simulate a conversation with multiple participants or on-thy-fly prompt rewriting.

```js
let turn = 0
defChatParticipant((_, messages) => {
    if (++turn === 1) _.$`Are you sure?`
})
```

In the example above, the `defChatParticipant` function is used to register a function that will be called every time a new message is added to the chat.

The function receives two arguments: the first argument is the `Chat` object, and the second argument is the list of messages that have been added to the chat since the last call to the function.

```js
defChatParticipant(async (_, messages) => {
  const text = messages.at(-1).content as string
  ...
})
```

## Tracking turns

[Section titled “Tracking turns”](#tracking-turns)

The participant will be called on every turn so it is important to keep track of the turns to avoid infinite loops.

```js
let turn = 0
defChatParticipant((_, messages) => {
    if (++turn === 1) _.$`Are you sure?`
})
```

## Rewriting messages

[Section titled “Rewriting messages”](#rewriting-messages)

To rewrite the message history, return a new list of new messages. The array of messages can be modified in place as it is already a structural clone of the original message history.

```js
defChatParticipant((_, messages) => {
    messages.push({
        role: "user",
        content: "Make it better!",
    })
    return { messages }
})
```

## Example: QA generator

[Section titled “Example: QA generator”](#example-qa-generator)

This script uses a multi-turn chat to generate questions, answers and validate the quality of the answers.

qa-gen.genai.mjs

```js
script({
  model: "small",
  title: "Multi-turn conversation",
  files: ["src/rag/markdown.md"],
  system: ["system", "system.files"],
  tests: {},
});


def("FILE", env.files);
$`Generate a set of questions for the files to build a FAQ.`;


// turn 2
let turn = 0;
defChatParticipant(
  async (ctx, messages) => {
    turn++;
    if (turn <= 1) {
      const text = messages.at(-1).content as string;
      const questions =
        text
          ?.split("\n")
          .map((q) => q.trim())
          .filter((q) => q.length > 0) || [];


      ctx.$`Here is the list of answers to the questions in the file.


## Task 1:


Validate the quality of the answer.


## Task 2:


Write the question/answers pairs for each file in a "<filename>.qt.jsonl" file
using the JSONL format:


\`\`\`\`markdown
File: <filename>.qt.jsonl
\`\`\`
${JSONL.stringify([
  { q: "<question1>", a: "<answer1>" },
  { q: "<question2>", a: "<answer2>" },
])}
...
\`\`\`
\`\`\`\`


### Questions:
            `;


      for (const question of questions) {
        const res = await runPrompt(
          (_) => {
            _.def("FILE", env.files);
            _.def("QUESTION", question);
            _.$`
## Roles


You are an expert educator at explaining concepts simply.


## Task


Answer the QUESTION using the contents in FILE.


## Instructions


- Use information in FILE exclusively.
- Be concise.
- Use simple language.
- use gitmojis.
`;
          },
          { label: question },
        );


        ctx.$`


- question: ${question}`;
        ctx.fence(res.text);
        ctx.$`\n\n`;
      }
    }
  },
  { label: "answerer" },
);
```