# Direção e fila

Dois padrões de interação permitem que os usuários enviem mensagens enquanto o agente já está em operação: direcionamento redireciona o agente no meio do turno e enfileiramento armazena mensagens em buffer para processamento sequencial após a conclusão do turno atual.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## Overview

Quando uma sessão está processando ativamente um turno, as mensagens de entrada podem ser entregues em um dos dois modos por meio do campo `mode` no `MessageOptions`:

| Modo                         | Behavior                                                     | Caso de uso                                                       |
| ---------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------- |
| `"immediate"` (direção)      | Injetado no turno LLM **atual**                              | "Na verdade, não crie esse arquivo — use uma abordagem diferente" |
| `"enqueue"` (enfileiramento) | Enfileirado e processado **após** a conclusão do turno atual | "Depois disso, corrija também os testes"                          |

![Diagrama: diagrama de sequência mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/features-steering-and-queueing-diagram-0.png)

## Direção (modo imediato)

O direcionamento envia uma mensagem que é injetada diretamente no turno atual do agente. O agente vê a mensagem em tempo real e ajusta sua resposta adequadamente, sendo útil para correção de curso sem anular o turno.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const session = await client.createSession({
    model: "gpt-5.4",
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

// Start a long-running task
const msgId = await session.send({
    prompt: "Refactor the authentication module to use sessions",
});

// While the agent is working, steer it
await session.send({
    prompt: "Actually, use JWT tokens instead of sessions",
    mode: "immediate",
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot import CopilotClient, PermissionDecisionApproveOnce

async def main():
    client = CopilotClient()
    await client.start()

    session = await client.create_session(
        on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
        model="gpt-5.4",
    )

    # Start a long-running task
    msg_id = await session.send(
        "Refactor the authentication module to use sessions",
    )

    # While the agent is working, steer it
    await session.send(
        "Actually, use JWT tokens instead of sessions",
        mode="immediate",
    )

    await client.stop()
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
package main

import (
    "context"
    "log"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)
    if err := client.Start(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Model: "gpt-5.4",
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    // Start a long-running task
    _, err = session.Send(ctx, copilot.MessageOptions{
        Prompt: "Refactor the authentication module to use sessions",
    })
    if err != nil {
        log.Fatal(err)
    }

    // While the agent is working, steer it
    _, err = session.Send(ctx, copilot.MessageOptions{
        Prompt: "Actually, use JWT tokens instead of sessions",
        Mode:   "immediate",
    })
    if err != nil {
        log.Fatal(err)
    }
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
using GitHub.Copilot;
using GitHub.Copilot.Rpc;

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    Model = "gpt-5.4",
    OnPermissionRequest = (req, inv) =>
        Task.FromResult(PermissionDecision.ApproveOnce()),
});

// Start a long-running task
var msgId = await session.SendAsync(new MessageOptions
{
    Prompt = "Refactor the authentication module to use sessions"
});

// While the agent is working, steer it
await session.SendAsync(new MessageOptions
{
    Prompt = "Actually, use JWT tokens instead of sessions",
    Mode = "immediate"
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

try (var client = new CopilotClient()) {
    client.start().get();

    var session = client.createSession(
        new SessionConfig()
            .setModel("gpt-5.4")
            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    // Start a long-running task
    session.send(new MessageOptions()
        .setPrompt("Refactor the authentication module to use sessions")
    ).get();

    // While the agent is working, steer it
    session.send(new MessageOptions()
        .setPrompt("Actually, use JWT tokens instead of sessions")
        .setMode("immediate")
    ).get();
}
```

</div>

</div>

### Como a direção funciona internamente

1. A mensagem é adicionada à fila `ImmediatePromptProcessor` do runtime
2. Antes da próxima solicitação do LLM no turno atual, o processador injeta a mensagem na conversa
3. O agente vê a mensagem de direção como uma nova mensagem de usuário e ajusta sua resposta
4. Se a curva for concluída antes que a mensagem de direção seja processada, ela será movida automaticamente para a fila regular para a próxima curva

> \[!NOTE]
> As mensagens de direcionamento são o melhor esforço no turno atual. Se o agente já tiver se comprometido com uma chamada da ferramenta, o direcionamento entrará em vigor após a conclusão dessa chamada, mas ainda dentro do mesmo turno.

## Fila (modo de enfileiramento)

O enfileiramento armazena em buffer as mensagens a serem processadas sequencialmente após a conclusão do turno atual. Cada mensagem enfileirada inicia seu próprio turno completo. Esse é o modo padrão, se você omitir `mode`, o SDK usará `"enqueue"`.

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
await client.start();

const session = await client.createSession({
    model: "gpt-5.4",
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

// Send an initial task
await session.send({ prompt: "Set up the project structure" });

// Queue follow-up tasks while the agent is busy
await session.send({
    prompt: "Add unit tests for the auth module",
    mode: "enqueue",
});

await session.send({
    prompt: "Update the README with setup instructions",
    mode: "enqueue",
});

// Messages are processed in FIFO order after each turn completes
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot import CopilotClient, PermissionDecisionApproveOnce

async def main():
    client = CopilotClient()
    await client.start()

    session = await client.create_session(
        on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
        model="gpt-5.4",
    )

    # Send an initial task
    await session.send("Set up the project structure")

    # Queue follow-up tasks while the agent is busy
    await session.send(
        "Add unit tests for the auth module",
        mode="enqueue",
    )

    await session.send(
        "Update the README with setup instructions",
        mode="enqueue",
    )

    # Messages are processed in FIFO order after each turn completes
    await client.stop()
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
// Send an initial task
session.Send(ctx, copilot.MessageOptions{
    Prompt: "Set up the project structure",
})

// Queue follow-up tasks while the agent is busy
session.Send(ctx, copilot.MessageOptions{
    Prompt: "Add unit tests for the auth module",
    Mode:   "enqueue",
})

session.Send(ctx, copilot.MessageOptions{
    Prompt: "Update the README with setup instructions",
    Mode:   "enqueue",
})

// Messages are processed in FIFO order after each turn completes
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
// Send an initial task
await session.SendAsync(new MessageOptions
{
    Prompt = "Set up the project structure"
});

// Queue follow-up tasks while the agent is busy
await session.SendAsync(new MessageOptions
{
    Prompt = "Add unit tests for the auth module",
    Mode = "enqueue"
});

await session.SendAsync(new MessageOptions
{
    Prompt = "Update the README with setup instructions",
    Mode = "enqueue"
});

// Messages are processed in FIFO order after each turn completes
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

try (var client = new CopilotClient()) {
    client.start().get();

    var session = client.createSession(
        new SessionConfig()
            .setModel("gpt-5.4")
            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    // Send an initial task
    session.send(new MessageOptions().setPrompt("Set up the project structure")).get();

    // Queue follow-up tasks while the agent is busy
    session.send(new MessageOptions()
        .setPrompt("Add unit tests for the auth module")
        .setMode("enqueue")
    ).get();

    session.send(new MessageOptions()
        .setPrompt("Update the README with setup instructions")
        .setMode("enqueue")
    ).get();

    // Messages are processed in FIFO order after each turn completes
}
```

</div>

</div>

### Como a fila funciona internamente

1. A mensagem é adicionada ao `itemQueue` da sessão como um `QueuedItem`
2. Quando o turno atual terminar e a sessão ficar ociosa, `processQueuedItems()` será executado
3. Os itens são removidos da fila na ordem FIFO, cada mensagem dispara um turno de agente completo
4. Se uma mensagem de direcionamento estava pendente quando o turno terminou, ela é movida para a frente da fila
5. O processamento continua até que a fila esteja vazia e, em seguida, a sessão emitirá um evento ocioso

## Combinar direcionamento e enfileiramento

Você pode usar os dois padrões juntos em uma única sessão. O direcionamento afeta o turno atual enquanto as mensagens enfileiradas esperam sua vez:

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const session = await client.createSession({
    model: "gpt-5.4",
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

// Start a task
await session.send({ prompt: "Refactor the database layer" });

// Steer the current work
await session.send({
    prompt: "Make sure to keep backwards compatibility with the v1 API",
    mode: "immediate",
});

// Queue a follow-up for after this turn
await session.send({
    prompt: "Now add migration scripts for the schema changes",
    mode: "enqueue",
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
session = await client.create_session(
    on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
    model="gpt-5.4",
)

# Start a task
await session.send("Refactor the database layer")

# Steer the current work
await session.send(
    "Make sure to keep backwards compatibility with the v1 API",
    mode="immediate",
)

# Queue a follow-up for after this turn
await session.send(
    "Now add migration scripts for the schema changes",
    mode="enqueue",
)
```

</div>

</div>

## Escolher entre direcionamento e enfileiramento

| Scenario                                                 | Pattern                                                     | Por que |
| -------------------------------------------------------- | ----------------------------------------------------------- | ------- |
| O agente está indo pelo caminho errado                   |                                                             |         |
| **Direcção**                                             | Redireciona o turno atual sem perder o progresso            |         |
| Você pensou em algo que o agente também deveria fazer    |                                                             |         |
| **Enfileiramento**                                       | Não interrompe o trabalho atual; é executado em seguida     |         |
| O agente está prestes a cometer um erro                  |                                                             |         |
| **Direcção**                                             | Intervém antes que o erro seja cometido                     |         |
| Você deseja encadear várias tarefas                      |                                                             |         |
| **Enfileiramento**                                       | A ordenação FIFO garante uma execução previsível            |         |
| Você deseja adicionar contexto à tarefa atual            |                                                             |         |
| **Direcção**                                             | O Agente incorpora-o ao seu raciocínio atual                |         |
| Você deseja enviar em lote solicitações não relacionadas |                                                             |         |
| **Enfileiramento**                                       | Cada um obtém seu próprio turno completo com contexto limpo |         |

## Criar uma interface de usuário com direcionamento e enfileiramento

Aqui está um padrão para criar uma interface do usuário interativa que dá suporte a ambos os modos:

```typescript
import { CopilotClient, CopilotSession } from "@github/copilot-sdk";

interface PendingMessage {
    prompt: string;
    mode: "immediate" | "enqueue";
    sentAt: Date;
}

class InteractiveChat {
    private session: CopilotSession;
    private isProcessing = false;
    private pendingMessages: PendingMessage[] = [];

    constructor(session: CopilotSession) {
        this.session = session;

        session.on((event) => {
            if (event.type === "session.idle") {
                this.isProcessing = false;
                this.onIdle();
            }
            if (event.type === "assistant.message") {
                this.renderMessage(event);
            }
        });
    }

    async sendMessage(prompt: string): Promise<void> {
        if (!this.isProcessing) {
            this.isProcessing = true;
            await this.session.send({ prompt });
            return;
        }

        // Session is busy — let the user choose how to deliver
        // Your UI would present this choice (e.g., buttons, keyboard shortcuts)
    }

    async steer(prompt: string): Promise<void> {
        this.pendingMessages.push({
            prompt,
            mode: "immediate",
            sentAt: new Date(),
        });
        await this.session.send({ prompt, mode: "immediate" });
    }

    async enqueue(prompt: string): Promise<void> {
        this.pendingMessages.push({
            prompt,
            mode: "enqueue",
            sentAt: new Date(),
        });
        await this.session.send({ prompt, mode: "enqueue" });
    }

    private onIdle(): void {
        this.pendingMessages = [];
        // Update UI to show session is ready for new input
    }

    private renderMessage(event: unknown): void {
        // Render assistant message in your UI
    }
}
```

## Referência de API

### Opções de Mensagem

| Linguagem | Campo  | Tipo                              | Default     | Description                  |
| --------- | ------ | --------------------------------- | ----------- | ---------------------------- |
| Node.js   | `mode` | `"enqueue" \| "immediate"`        | `"enqueue"` | Modo de entrega de mensagens |
| Python    | `mode` | `Literal["enqueue", "immediate"]` | `"enqueue"` | Modo de entrega de mensagens |
| Go        | `Mode` | `string`                          | `"enqueue"` | Modo de entrega de mensagens |
| .NET      | `Mode` | `string?`                         | `"enqueue"` | Modo de entrega de mensagens |

### Modos de entrega

| Modo          | Efeito                    | Durante o turno ativo                 | Durante a inatividade               |
| ------------- | ------------------------- | ------------------------------------- | ----------------------------------- |
| `"enqueue"`   | Fila para a próxima curva | Esperas na fila FIFO                  | Inicia uma nova curva imediatamente |
| `"immediate"` | Injetar no turno atual    | Injetado antes da próxima chamada LLM | Inicia uma nova curva imediatamente |

> \[!NOTE]
> Quando a sessão está ociosa (não processando), ambos os modos se comportam de forma idêntica– a mensagem inicia um novo turno imediatamente.

## Práticas recomendadas

1. **Definir como padrão o enfileiramento** — usar `"enqueue"` (ou omitir `mode`) para a maioria das mensagens. É previsível e não corre o risco de interromper o trabalho em andamento.

2. **Reservar o direcionamento para correções** — usar `"immediate"` quando o agente estiver fazendo algo errado ativamente e for necessário redirecioná-lo antes que ele avance ainda mais.

3. **Manter as mensagens de direcionamento concisas** — o agente precisa entender rapidamente a correção do curso. Mensagens de direção longas e complexas podem confundir o contexto atual.

4. **Não direcione demais**— várias mensagens de direção rápidas podem prejudicar a qualidade da curva. Se você precisar alterar significativamente a direção, considere anular a curva e iniciar novamente.

5. **Mostrar o estado da fila na interface do usuário** — exiba o número de mensagens enfileiradas para que os usuários saibam o que está pendente. Monitore eventos de inatividade para limpar a tela.

6. **Manipular o fallback de direcionamento para fila** — se uma mensagem de direcionamento chegar após a conclusão do turno, ela será movida automaticamente para a fila. Crie sua interface do usuário para refletir essa transição.

## Consulte também

* [Crie seu primeiro aplicativo com tecnologia do Copilot](/pt/copilot/how-tos/copilot-sdk/getting-started): Configurar uma sessão e enviar mensagens
* [Agentes personalizados e orquestração de subagentes](/pt/copilot/how-tos/copilot-sdk/features/custom-agents): Defina agentes especializados com ferramentas de escopo definido
* [Ganchos de sessão](/pt/copilot/how-tos/copilot-sdk/hooks/hooks-overview): Reagir a eventos do ciclo de vida da sessão
* [Retomada e persistência da sessão](/pt/copilot/how-tos/copilot-sdk/features/session-persistence): Retomar sessões entre reinicializações