Custom agents missing from 'Environment loaded' startup message due to race condition
- Dominant language
- Shell
- Stars
- 11.2k
- Forks
- 1.9k
- Avg merge
- 14h 16m
- Merged PRs (30d)
- 6
Description
## Description
Custom agents defined in `.github/agents/` are properly detected and usable via `/agent`, but they do not appear in the "Environment loaded" startup message. The message shows instructions, skills, and MCP servers, but omits the agent count.
**Expected:** `Environment loaded: 4 custom instructions, 1 MCP server, 58 skills, 38 agents`
**Actual:** `Environment loaded: 4 custom instructions, 1 MCP server, 58 skills`
Agents are fully functional — `/agent` lists all 38 custom agents correctly.
## Root Cause Analysis
After analyzing `app.js` (v1.0.5), the startup reporter (`Ybt` class) fires its `onComplete` callback exactly once — the first time all **registered** participants are done. The issue is a registration timing race:
1. **Instructions** (`VIo`), **Skills** (`XIo`), and **Plugins** (`QIo`) register their reporter participants immediately via `useEffect`.
2. **Agents** (`FIo`) only registers its participant **after** the async `RAe` call completes (when `fI.loaded` becomes `true`).
```js
// Agents only register when loaded — too late if others already completed
(0,ke.useEffect)(()=>{
fI.loaded && FIo(YI, fI.available.length)
}, [YI, fI.available.length, fI.loaded]);
```
If instructions, skills, and plugins all complete before `fI.loaded` becomes `true`, the reporter sees all registered participants as done, fires `onComplete`, and the startup message is emitted **without agents**. When agents finally load and `FIo` registers a new participant, the completion callback has already been emitted (guarded by `_completionEmitted` flag).
The `RAe` function includes a remote API call (`/agents/swe/custom-agents/{owner}/{repo}`) which adds latency, making this race likely for repos with many agents or slower API responses.
## Suggested Fix
**Option A: Pre-register the agents participant before async loading starts**
Register the "agents" participant eagerly so the reporter waits for it:
```js
// Register immediately, report items later when loaded
(0,ke.useEffect)(() => {
let participant = YI.register("agents");
// Will be updated when agents load
return () => {}; // cleanup
}, [YI]);
(0,ke.useEffect)(() => {
if (fI.loaded) {
// Reporter already knows about "agents" participant, just update and mark done
FIo(YI, fI.available.length);
}
}, [YI, fI.available.length, fI.loaded]);
```
**Option B: Add a timeout/debounce to the reporter completion**
Delay the `onComplete` emission briefly (e.g., 500ms) to allow async participants to register, or use a known list of expected participants.
## Environment
- **CLI version:** 1.0.5
- **OS:** macOS (Darwin arm64)
- **Node.js:** v24.11.1
- **Custom agents:** 38 (in `.github/agents/`)
- **Reproduction:** Consistent across multiple CLI restarts
## Steps to Reproduce
1. Create a repository with 30+ custom agents in `.github/agents/`
2. Launch `copilot` in the repository
3. Observe the "Environment loaded" message — agents are missing
4. Run `/agent` — all agents are listed correctly
Contributor guide
Assessment
This issue has not been assessed yet.