Supervisor-Subagent Architecture, Tool Routing, and the Trust Boundary
Inline agents: InvokeInlineAgent API shape, action group assembly, IAM trust boundary. Supervisor-subagent pattern for dynamic tool-surface orchestration.
Copilot Extensions API: GitHub App as extension backend, stateless vs agent-backed extension patterns, permission scope as trust ceiling.
Most Bedrock agent implementations start the same way: a pre-configured agent resource in the AWS console, a fixed action group, a bound knowledge base. That configuration is durable and auditable. It is also static. The supervisor knows at deploy time which tools the agent has.
Inline agents break that assumption. An inline agent is invoked directly in code without a pre-configured agent resource in Bedrock. The calling code passes the model ID, the instructions, the action groups, and the tool definitions at invocation time. Nothing is registered in the console; everything travels in the API call. This is the correct pattern when orchestration needs are dynamic — when the supervisor must assemble the right set of tools for a task at call time rather than at configuration time.
The tradeoff is the trust boundary. A pre-configured agent carries an IAM role at configuration time; that role is visible and auditable before any task runs. An inline agent carries permissions at invocation time; the calling code determines what the agent can reach. The supervisor is accountable for the tool surface it hands down.
A standard Bedrock agent has an ARN, a version, an alias, an IAM execution role, and action groups registered at configuration time. An inline agent replaces the resource lookup with inline parameters. The InvokeInlineAgent call accepts:
The agent's ReAct loop runs against those parameters identically to a standard agent. What differs is that the action groups arrived at call time rather than at configuration time.
The practical shape of an inline agent orchestration is a supervisor that reasons over a task and dispatches to one or more subagents. Each subagent is itself an inline agent invocation with a narrow tool set appropriate to its sub-task. The supervisor has three responsibilities: parse the incoming task into sub-tasks; for each sub-task, select the action groups appropriate to that work; collect the subagent results and synthesize the final response.
Supervisor classifies the task from a closed vocabulary, applies a pre-coded label → action group set mapping. Deterministic, auditable, low-latency. Correct when task types are well-enumerated.
Supervisor passes all available action group definitions to the model; model selects which ones the task needs. Flexible but adds a model call to the critical path; selection uncertainty possible.
Supervisor maintains a registry of specialist subagent profiles (instruction + action group set) keyed to domain. Classification loads the profile. Deterministic; profile updates propagate to all future calls.
For Lambda-backed action groups, the Lambda's IAM execution role is the hard ceiling on what the action group can actually do. The model proposes an action; the action group routes it to a Lambda; the Lambda's role governs the actual execution. The model cannot exceed the Lambda's role regardless of what it reasons it needs.
A Copilot extension is a GitHub App that registers as a Copilot agent. When a user invokes the extension from the Copilot Chat sidebar (via @extension-name), GitHub routes the conversation to the extension's backend. The extension receives the conversation history, the user's message, and a context payload (current file, repository, branch), then responds with a stream of server-sent events.
From the supervisor's perspective, the Copilot Chat interface is the supervisor. It routes the mention to the correct extension backend and renders the streaming response. The extension receives a scoped task and produces a response.
InvokeInlineAgent call, stream the Bedrock response back through the GitHub SSE format. This is the integration point between the two cert domains.A Copilot extension runs in the extension developer's infrastructure, not in the user's GitHub account. The extension receives only the data GitHub forwards in the payload. Access to GitHub resources requires explicit GitHub App permissions granted at installation. The extension's declared permissions are the hard ceiling on what it can do with the user's GitHub resources, regardless of what the reasoning layer determines.
InvokeAgent and InvokeInlineAgent in Amazon Bedrock?
▼
InvokeAgent calls a pre-configured agent resource registered in Bedrock with a fixed IAM role, action groups, and knowledge bases. InvokeInlineAgent passes all agent parameters — model ID, instruction, action groups — inline at call time; no agent resource is registered in Bedrock. Inline agents enable dynamic tool-surface assembly at invocation time.
contents:read during installation. A user asks the extension to delete a file from their repository. What happens?
▼
contents:read. Deleting a file requires contents:write. The extension cannot exceed the permissions granted at installation, regardless of what the user requests or what the extension's reasoning layer determines. The trust boundary is the GitHub App permission set.
InvokeInlineAgent call, assembling the instruction and action groups appropriate to the task. It streams the Bedrock response back to GitHub in the server-sent events format Copilot Chat expects. The extension handles the protocol translation; Bedrock handles the reasoning loop.
An inline agent is a tool surface assembled in code rather than configured in a console. The supervisor writes the agent at call time. The trust boundary is still the IAM role on the Lambda; the behavioral telemetry is still the audit stream. What changes is accountability: the supervisor's code is now the configuration artifact. Read it as such. Audit what action groups it assembles. Monitor what Lambda ARNs it targets. Baseline the pattern.
The Copilot extension applies the same principle one layer up: the extension developer writes the GitHub App; the permission set is the trust boundary; the user's authorization is the consent record. Both systems enforce the same architecture: delegate to a bounded context, instrument the delegation, gate on deviation.
The trust boundary is not a wall the system builds for you. It is a declaration you make at configuration time and must then defend through monitoring. Examine this well.