> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Choose who is in a Session

> Add and remove the people and agents in a Buyer account Session, and choose its lead, with save_session.

A Buyer account Session is a chat. It can hold people from your account, buyer
agents that work for your account, and the Apostra assistant. `save_session`
changes who is in one, and which of them leads it.

> [!NOTE]
>
> This is in beta and is switched on per organization, together with
> [chatting with your buyer agent](https://docs.apostra.com/v3/chat-with-your-buyer-agent.md). Until it is
> on for your account, `save_session` is not listed for a Buyer account and a
> call to it is refused with `FEATURE_NOT_ENABLED`. Ask your Apostra contact to
> turn it on.

> [!NOTE]
>
> A message that names agents is answered by those agents, and a message that
> names nobody is answered by the lead, so changing the lead changes who answers.
> `get` does not yet list a Session's participants; that follows in a separate
> release.

## Who can be in a Session

Each participant is one of three kinds:

| Kind | Who | Identified by |
| - | - | - |
| `human` | A person with access to your account | `userId` |
| `agent` | A buyer agent that works for your account | `principalId` |
| `assistant` | The Apostra assistant | Nothing more. There is only one. |

A person must be an active member of your account. Someone outside it cannot
be added.

An agent must be active, and must work for your account: either the account's
own agent, or a hosted or external buyer agent that holds an advertiser grant
on your account. If the Session concerns one advertiser, the agent must be
able to act for that advertiser. The Session's advertiser is the one recorded
on it or, when none is recorded, the advertiser the chat was started in, if
your account owns it. If both are set and they differ, or the chat was started
in an advertiser your account does not own, only your account's own agent can
take part. A chat started at the account level has no advertiser, and only the
account-level check applies. See
[Hosted buyer agents](https://docs.apostra.com/v3/hosted-buyer-agents.md) and
[Advertiser grants](https://docs.apostra.com/v3/advertiser-grants.md).

The rule applies after the agent is added too. If an agent's account relationship
or grant is revoked, or the Session starts to concern an advertiser its grants do
not cover, the agent stays on the list of participants, is no longer listed as active, cannot
be addressed, and does not answer. If it is the lead and it was suspended, retired
or no longer covers the Session, a message that names nobody is refused before it
is stored, naming the agent, and is never handed to another agent; the reply to a
participant change says so. If the lead was only suspended or retired, name a new
lead with `save_session`. If it lost its grant, no longer covers the Session's
advertiser or no longer works for your organization, name the new lead and remove
the old one in the same call (`inSession: false`), because it cannot stay as a
participant. Or restore the grant. A Session that started
before participants were stored keeps its bound agent as lead when it is first
changed, even if that agent can no longer take turns, but leaves out a room agent
that could not be addressed anyway.

The account's organization agent, used from a child account, may lead a Session
there without a grant on that account, because it acts with no authority on it. It
cannot join as a plain participant. An agent that holds any grant on the account,
active or revoked, must cover the Session's advertisers to lead.
Naming a new lead while that organization agent leads is refused unless the same
call removes it (`inSession: false`), because demoting it would leave it as a
plain participant. The first message of a new chat is checked the same way as
later ones: one that would hand the lead to another agent while that organization
agent leads is refused, naming it, and writes nothing. Remove it with
`save_session` first.

The Apostra assistant can always be added.

## Roles

Every agent, and the assistant, has a role. A person has none.

| Role | What it is for |
| - | - |
| `lead` | Answers when nobody is addressed. Every Session has exactly one. |
| `expert` | There to be asked. The lead sees its experts first. |
| `participant` | Answers when it is addressed. |

A new Session starts with the Apostra assistant as its lead. A Session that was
started with one of your buyer agents keeps that agent as its lead.

## Change who is in a Session

Pass `sessionId` and up to ten `participants`. An entry with `inSession: true`
adds that participant, or changes its role if it is already in. An entry with
`inSession: false` removes it. An entry that matches what is already true
changes nothing and records nothing.

```json theme={null}
{
  "sessionId": "2f6c1b2e-8a44-4d19-9c3e-5b7a0d21f8ac",
  "participants": [
    { "kind": "human", "userId": "4012", "inSession": true },
    {
      "kind": "agent",
      "principalId": "prin_yq8Kd0example0000000000000000",
      "role": "lead",
      "inSession": true
    }
  ]
}
```

The call returns everyone in the Session afterwards, each with `kind`,
`userId`, `principalId`, `role` and `addedAt`. When the lead is an agent that
cannot take turns, the text of the reply adds one line naming it and the reason.

A call is a participant change or a private note, never both. Sending `note`,
`action`, `clientRequestId` or `throughEventId` with `participants` is
refused, and the refusal names the field.

### Change the lead

Set `role: "lead"` on the participant who should lead. The previous lead
becomes an `expert` if it still works for your account and covers the Session,
unless the same call changes or removes it. If it no longer qualifies, the call is
refused, naming it, unless the same call also removes it. A Session
always keeps a lead, so removing the lead without naming a new one in the same
call is refused.

### Limits

* At most 5 agents in a Session, not counting the assistant.
* At most 100 participants in all.
* At most 10 entries in one call.
* Starting a chat with an agent follows the same limits and eligibility rules. If a
  Session already has 5 agents or 100 participants, the first message to another
  agent is refused and tells the person to remove someone first. An agent that is already a participant
  is made lead without changing the count.
* A Session that began before participants were stored is moved over the first time
  its participants change, and every person in it comes along. If its people and
  agents together would be more than 100, the change is refused and nothing moves.
  Each room agent left out is named in a Session event line with the reason.

## Who can change it

A person signed in to the Buyer account as themselves, who holds write access
on the account and can read the Session. In this release that means the person
who started it, or any member of the account while the Session is shared.
Anyone with that access can add or remove people and agents and change the lead.

* The person who started the Session cannot be removed.
* Any person who can read the Session can remove themselves.
* An agent cannot change who is in a Session.
* An impersonated or simulated session, and a credential with no acting user,
  are refused.

Adding a person to a private chat records them as a participant. It does not
let them read or change the chat yet, and neither does having posted in a chat
that has since stopped being shared; that waits for a security review.

## Refusals

Each refusal says what is wrong.

| Case | Code |
| - | - |
| The Session does not exist, or you cannot read it | `NOT_FOUND` |
| You may not make this change | `ACCESS_DENIED` |
| A `principalId` is not a buyer agent of your account | `VALIDATION_ERROR` |
| The agent is suspended or retired | `VALIDATION_ERROR` |
| The agent's grants do not cover the advertiser the Session concerns | `VALIDATION_ERROR` |
| A `userId` is not an active member of your account | `VALIDATION_ERROR` |
| More than 5 agents or 100 participants | `VALIDATION_ERROR` |
| The change leaves no lead, or removes the owner | `VALIDATION_ERROR` |
| The `buyer-agent-chat` value is off for your account | `FEATURE_NOT_ENABLED` |

An agent that belongs to another account is refused with the same message as
an agent that does not exist, so a call cannot be used to find out which agents
other accounts have.

## What is recorded

Each change appears in the Session as a line that names who made it, for
example "Brian added Water category agent" or "Prime is now the lead". Adding a
person or an agent does not notify them.

## The earlier Murph tool

The Murph tool `set_conversation_agent_participants` is retired. It only set
agents, only for the person who started the chat. A call to it now returns a
refusal that points to `save_session`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.