Welcome to the third chapter of the Teams project tutorial!
In previous chapters, we established who is on the team (Teammate Entity & Discovery) and what they are working on (Task Assignment).
Now we face a critical safety question: How much power do we give them?
Imagine you hire a junior intern. You might trust them to read documents, but you probably want to double-check their work before they delete files or deploy code to production.
As the intern gains trust, you might give them more autonomy.
In our system, AI agents are like that intern. We need a way to dynamically shift their "Security Clearance" between different levels:
The Problem: We need a way to toggle these states instantly without restarting the agent, and we need to see at a glance what permissions an agent has.
The Solution: Permission Mode Control. A governance layer that manages the state of trust and visualizes it with colors (Red/Green) and symbols.
In this chapter, we will build the logic that allows a user to press Shift+Tab in the UI to cycle an agent from "Ask Permission" mode to "Full Autonomy" mode.
'default', 'bypassed', 'read-only').fs.delete_file) is allowed to run.Default -> Bypass -> ReadOnly -> Default).To the user, this system appears as a visual badge next to the agent's name.
In the UI, we don't show raw text like "mode: bypassed". We translate that state into a color and a symbol.
Input: A mode string (e.g., 'bypassed').
Output: A Red color and a specific symbol.
Here is how the UI component decides what to draw:
// Inside TeammateListItem.tsx
// 1. Convert string to a typed mode
const mode = permissionModeFromString(teammate.mode);
// 2. Get the symbol (e.g., a shield or a lightning bolt)
const modeSymbol = permissionModeSymbol(mode);
// 3. Get the color (e.g., Red for high-risk/bypass)
const modeColor = getModeColor(mode);
Explanation:
permissionModeFromString: Sanitizes the data coming from the backend.permissionModeSymbol: Returns a character like β‘ (Bypass) or π (Safe).getModeColor: Returns a UI theme color string.When the user wants to change permissions, they press a key. We use a "Cycler" function to determine the next state.
// Inside TeamsDialog.tsx
function cycleTeammateMode(teammate: TeammateStatus, /*...*/) {
const currentMode = teammate.mode ?? 'default';
// Create a context to determine valid next moves
const context = {
mode: currentMode,
isBypassPermissionsModeAvailable: true
};
// Calculate next mode (e.g. Default -> Bypass)
const nextMode = getNextPermissionMode(context);
// Apply the change
sendModeChangeToTeammate(teammate.name, teamName, nextMode);
}
Explanation:
getNextPermissionMode: This is a state machine. It knows that after "Standard" comes "Bypass", and after "Bypass" comes "Read Only".sendModeChangeToTeammate: This triggers the actual update logic.Changing a permission mode is a two-step process. We must update the Persistent Config (so the UI remembers it) and notify the Live Agent (so they stop asking for permission immediately).
Shift+Tab.config.json. The UI reads this file to update the color immediately.Why do we update two things?
Here is the helper function that handles both:
// Inside TeamsDialog.tsx
function sendModeChangeToTeammate(
teammateName: string,
teamName: string,
targetMode: PermissionMode
): void {
// 1. Update persistent config (UI updates immediately via React state)
setMemberMode(teamName, teammateName, targetMode);
// 2. Prepare the message payload
const message = createModeSetRequestMessage({
mode: targetMode,
from: 'team-lead'
});
// 3. Send via Mailbox Protocol
void writeToMailbox(teammateName, {
from: 'team-lead',
text: jsonStringify(message),
timestamp: new Date().toISOString()
}, teamName);
}
Explanation:
setMemberMode: Writes to the JSON database.createModeSetRequestMessage: Formats a standardized command object.writeToMailbox: Drops the letter in the agent's inbox.We will explore exactly how the agent reads that letter in the next chapter, Agent Communication (Mailbox Protocol).
Sometimes you want to unlock the whole team at once. The system supports "Batch Cycling".
// Inside TeamsDialog.tsx
function cycleAllTeammateModes(teammates: TeammateStatus[], /*...*/) {
// 1. Check if everyone is on the same mode
const allSame = modes.every(m => m === modes[0]);
// 2. If mixed, reset everyone to default. If same, move everyone forward.
const targetMode = !allSame ? 'default' : getNextPermissionMode(/*...*/);
// 3. Update everyone at once
setMultipleMemberModes(teamName, modeUpdates);
// 4. Loop through and notify every agent
for (const teammate of teammates) {
// ... send mailbox message ...
}
}
In this chapter, we learned:
Now we have a secure way to control our agents. But waitβhow exactly does that "Mailbox Message" work? How do agents talk to us, and how do they talk to each other?
Next Chapter: Agent Communication (Mailbox Protocol)
Generated by Code IQ