Welcome to the first chapter of the Teams project tutorial!
In this series, we will build a system where AI agents work together like a real software development team. Before we can assign tasks or let agents talk to each other, we need to answer a fundamental question: Who is on the team?
Imagine walking into a physical office. To know who is working today, you might look at the desks.
In our software, an "AI Agent" isn't a physical person. It is a computer process running in the background (specifically, inside a tool called tmux).
The Problem: How do we bridge the gap between a raw computer process (Process ID: 12345) and a helpful teammate named "Alice"?
The Solution: The Teammate Entity & Discovery system. It acts as a dynamic roster that constantly checks "who is at their desk" and reports their status to the UI.
Throughout this chapter, we will look at how the Team Dialog works. This is the menu you see when you want to list all your active AI teammates.
To understand this chapter, we need to define three simple concepts:
tmux pane they live in).In our application, we don't usually call "Discovery" functions manually. Instead, the User Interface (UI) components automatically ask for this data.
At the bottom of the screen, there is a small indicator showing how many teammates are online.
Input: The application state (which contains the list of discovered agents).
Output: A text string like "3 teammates".
Here is how the code calculates that number:
// Inside TeamStatus.tsx
// We get the teamContext from the global application state
const teamContext = useAppState(s => s.teamContext);
// We count the teammates, excluding the 'team-lead' (which is the user)
const totalTeammates = teamContext
? Object.values(teamContext.teammates)
.filter(t => t.name !== 'team-lead')
.length
: 0;
Explanation:
useAppState: Hooks into the global memory of the app.Object.values: Converts the roster into a list.filter: We remove the "team-lead" because that is you (the human), not an AI agent.
When you press Enter on the status, a dialog opens listing everyone. This dialog needs to stay fresh. If an agent crashes or finishes a task, the UI must update.
// Inside TeamsDialog.tsx
// This hook runs the code inside it every 1000 milliseconds (1 second)
useInterval(() => {
// Incrementing this key forces the list to re-read data
setRefreshKey(k => k + 1);
}, 1000);
Explanation:
useInterval: A timer that ticks every second.setRefreshKey: By changing a piece of state, we force the "Discovery" logic to run again, ensuring our list is never stale.How does the system actually manage these entities? It's a loop of checking reality vs. data.
%4 is "Agent Smith").Here is what happens when you open the Team Dialog:
Sometimes, a teammate isn't needed anymore. You might want to "fire" (kill) a teammate process. This involves cleaning up three layers: the Process, the Config, and the State.
Here is the logic for removing a teammate:
// Inside TeamsDialog.tsx
async function killTeammate(
paneId: string,
backendType: PaneBackendType | undefined,
// ... other params
) {
if (backendType) {
// 1. Kill the actual OS process (The Pane)
await getBackendByType(backendType).killPane(paneId, !isInsideTmuxSync());
}
Explanation:
Once the process is dead, we need to tell the rest of the app:
// 2. Remove them from the permanent team configuration
removeMemberFromTeam(teamName, paneId);
// 3. Unassign any work they were doing
// (We will cover tasks in Chapter 2)
await unassignTeammateTasks(teamName, teammateId, teammateName, 'terminated');
Explanation:
Finally, we update the UI immediately:
// 4. Update the AppState so the UI removes the name immediately
setAppState(prev => {
// ... logic to remove the specific teammate ID from the list ...
return {
...prev,
teamContext: {
...prev.teamContext,
teammates: remainingTeammates // The list without the killed agent
}
};
});
}
Explanation:
setAppState to manually remove the agent from memory. This makes the UI feel instant, even if the background cleanup takes a few milliseconds.Besides killing processes, we can also change how much power a teammate has. This is called their Permission Mode.
// Inside TeamsDialog.tsx
function cycleTeammateMode(teammate: TeammateStatus, /*...*/) {
// Calculate the next mode (e.g., read-only -> full-access)
const nextMode = getNextPermissionMode(context);
// Send a message to the agent telling them their permissions changed
sendModeChangeToTeammate(teammate.name, teamName, nextMode);
}
Explanation:
mode.In this chapter, we learned:
%1).Now that we have a team assembled and we know who is online, we need to give them something to do!
Generated by Code IQ