The Gap Between Prototype and Production
Most AI engineering teams can build a working agent in a day. The hard part is not building it; the hard part is operating it. Prompts drift. Tool configurations change without review. Deployments happen from someone's laptop. There is no audit trail, no rollback plan, and no consistent way to promote a change from a development environment to production.
GitOps closes that gap. By treating your agent definition, configuration, and infrastructure as version-controlled source code, you get the same delivery discipline that software engineering teams have applied to application code for years. Every change is reviewed, every deployment is automated, and every environment state is traceable to a specific commit.
This post shows you how to apply GitOps principles to a Microsoft Foundry Hosted Agent using GitHub as the source of truth and GitHub Tasks and Actions as the automation layer. The result is a repeatable, governed, production-ready delivery model for AI agents.
What Is a Microsoft Foundry Hosted Agent?
Microsoft Foundry is Microsoft's platform for building, deploying, and operating AI applications and agents. A Hosted Agent is an agent runtime managed by the Foundry platform rather than self-hosted by your team. You supply the agent logic, configuration, and tools; Foundry handles the runtime lifecycle, scaling, and managed infrastructure.
In practical terms, a Foundry Hosted Agent is a containerised agent application. You package your agent code, prompt definitions, tool bindings, and environment configuration into a container image. Foundry deploys and manages that container within a Foundry project, connected to models, tools, and observability infrastructure that the platform provides.
Teams choose Hosted Agents over self-hosting because:
- The platform manages runtime infrastructure, patching, and scaling
- Integration with Azure AI models, managed identity, and observability is built in
- You can focus engineering effort on agent logic rather than cluster management
- Foundry projects provide environment and resource isolation without requiring you to provision and manage separate Azure resources for each environment
Hosted Agents are a good fit when your team wants strong operational support with minimal platform overhead, when you need clear separation between environments, and when your agents depend on Azure AI capabilities such as Azure OpenAI Service, Azure AI Search, or Model Context Protocol integrations.
Why GitOps Matters Specifically for AI Agents
GitOps is straightforward for stateless web services: the code changes, the pipeline runs, the container is deployed. AI agents are more complex because there are multiple distinct artefacts that all affect agent behaviour:
- System prompts and instruction files
- Tool definitions and external integrations
- Model selection and configuration (temperature, max tokens, safety settings)
- Model Context Protocol (MCP) server definitions
- Orchestration logic and agent workflow code
- Safety and policy settings
- Infrastructure and deployment configuration
Any one of these can change the behaviour of your agent in ways that are difficult to detect without structured review. A prompt change that looks harmless can alter tone, scope, or factual grounding. A tool configuration change can expose data to unintended callers. A model upgrade can shift response quality unpredictably.
Git gives you a single place to version, review, and approve all of these artefacts together. Pull requests give you a structured review gate. Workflow automation gives you validation before anything reaches a deployed environment. Tags and releases give you deployment markers you can roll back to.
The discipline of GitOps turns what is often an ad-hoc AI delivery process into a repeatable engineering practice.
Reference Architecture
The following diagram shows a practical reference architecture for delivering a Microsoft Foundry Hosted Agent through a GitOps model using GitHub.
+---------------------------+
| GitHub Repository |
| /src /agents /tools |
| /prompts /infra |
| /.github/workflows |
+---------------------------+
|
| Pull Request / Push to main
v
+---------------------------+
| GitHub Actions |
| 1. Validate agent config |
| 2. Lint and scan code |
| 3. Run unit tests |
| 4. Build container image |
| 5. Push to registry |
+---------------------------+
|
| Image tag (SHA or semver)
v
+---------------------------+
| Azure Container Registry |
| myregistry.azurecr.io |
| my-agent:<sha> |
+---------------------------+
|
+------+------+
| |
v v
+----------+ +----------+
| Foundry | | Foundry |
| Dev | | Test |
| Project | | Project |
+----------+ +----------+
|
Approval gate (GitHub env)
|
v
+----------+
| Foundry |
| Prod |
| Project |
+----------+
|
v
+---------------------------+
| Observability |
| Azure Monitor / App |
| Insights / Foundry Logs |
+---------------------------+
Key design decisions in this architecture:
- The GitHub repository is the single source of truth for all agent artefacts
- No human deploys directly to any Foundry project; all changes flow through automation
- Environment promotion requires a GitHub environment approval, creating a governance gate
- The container image is built once and promoted across environments; the image is not rebuilt per environment
- Secrets are stored in Azure Key Vault and accessed by the Foundry agent at runtime via managed identity
Figure: GitOps delivery pipeline stages from commit to production
Repository Structure
A well-structured repository separates agent logic from infrastructure and tooling from prompts. The following structure works well in practice:
my-foundry-agent/
├── .github/
│ ├── workflows/
│ │ ├── validate.yml # Runs on every PR
│ │ ├── build-deploy.yml # Runs on merge to main
│ │ └── rollback.yml # Manual trigger workflow
│ └── CODEOWNERS # Review assignments by path
├── src/
│ ├── agents/
│ │ ├── agent.py # Agent entry point and orchestration
│ │ └── agent_config.json # Agent metadata and settings
│ ├── tools/
│ │ ├── search_tool.py # Tool implementations
│ │ └── data_tool.py
│ └── prompts/
│ ├── system.txt # System prompt (versioned as plain text)
│ └── instructions.txt # Supplementary instructions
├── tests/
│ ├── unit/ # Unit tests for tools and logic
│ ├── integration/ # Integration tests against a running agent
│ └── smoke/ # Post-deployment smoke tests
├── infra/
│ ├── main.bicep # Foundry project and resource definitions
│ └── environments/
│ ├── dev.parameters.json
│ ├── test.parameters.json
│ └── prod.parameters.json
├── scripts/
│ ├── validate_agent.py # Config validation script
│ └── smoke_test.py # Smoke test runner
├── Dockerfile # Container image definition
└── docs/
└── architecture.md # Architecture and runbook documentation
What belongs where and why:
- /src/prompts - System prompts as plain text files. Versioning prompts as files means every change goes through a pull request with a diff review, just as code does.
- /src/agents - Agent orchestration logic and configuration. Keeps the entry point and agent metadata co-located.
- /src/tools - Tool implementations separated from agent logic. Tool logic changes independently and should be reviewable in isolation.
- /infra - Infrastructure as code with per-environment parameter files. Environment-specific values live here, never in source files.
- /tests - Three layers of testing: unit tests for tools, integration tests for the full agent, and smoke tests that run against a deployed environment.
- /.github/workflows - All automation defined as code. There should be no manual deployment steps that live outside this directory.
GitHub Tasks Across the Delivery Lifecycle
GitHub Tasks and Issues provide the work tracking layer on top of the GitOps delivery model. Used well, they connect the intention behind a change to its implementation and deployment history.
Practical patterns for using GitHub Tasks with agent delivery:
- Prompt change task - Open an issue to describe why the system prompt is changing. The pull request that changes
system.txtcloses that issue, creating a permanent link between the rationale and the diff. - Tool integration task - When adding a new MCP server or external tool integration, create a task that captures the design decision, security review outcome, and test evidence before the pull request is merged.
- Model upgrade task - When upgrading the underlying model version, create a task that includes evaluation results and comparison data. The task becomes part of your change audit trail.
- Rollback task - If a deployment causes quality regressions, create a task to track the rollback, root cause investigation, and corrective action. Automation can open this task automatically when a deployment fails health checks.
- Dependency on approval - GitHub Tasks can be linked to environment approvals in GitHub Actions. A task in a specific milestone or project column can gate a promotion workflow.
The key insight is that GitHub Tasks are not just work management; they are part of your audit trail. A regulatory or security reviewer can follow the chain from a production deployment back through workflow runs, pull request reviews, and the original task that described the intent of the change.
End-to-End GitOps Flow
The following walk-through describes a realistic developer experience for changing an agent prompt and promoting it to production.
- A developer opens a GitHub Issue describing the prompt change required and the expected behaviour improvement.
- The developer creates a feature branch, edits
src/prompts/system.txt, and updates any related unit tests. - A pull request is opened. The validate workflow runs immediately, checking prompt length, configuration schema, and lint rules. Unit tests run against the changed files.
- A code reviewer approves the pull request. The CODEOWNERS file ensures that prompt changes require review from the AI engineering team, not just any contributor.
- On merge to main, the build workflow runs: the container image is built with the new prompt baked in, tagged with the commit SHA, and pushed to Azure Container Registry.
- The deployment workflow deploys the new image to the Foundry Dev project automatically. Integration and smoke tests run against the deployed dev agent.
- If tests pass, the workflow pauses at the Test environment gate and requests approval from a named reviewer.
- After approval, the same image is deployed to Foundry Test. Smoke tests run again.
- A second approval gate controls promotion to Foundry Prod.
- If at any point a health check or smoke test fails, the rollback workflow redeploys the previous image tag from the registry. The image tag of the last known-good deployment is stored as a GitHub environment variable.
This flow means that no human ever deploys directly to any environment. Every environment state is traceable to a specific commit, image tag, and workflow run.
Security and Governance
AI agents often have access to sensitive data and external systems. Security and governance cannot be an afterthought.
Identity and Access
- Use managed identity for the Foundry Hosted Agent to access Azure resources. Avoid service principal secrets where Microsoft Entra Workload Identity or managed identity is available.
- Apply the principle of least privilege: the agent identity should have read access to data sources and limited write access only where the use case requires it.
- Tool integrations that require API keys or external credentials should retrieve them from Azure Key Vault at runtime, never from environment variables baked into the image.
Secrets and Configuration
- Store secrets in Azure Key Vault. Reference them in your Foundry project configuration using Key Vault references.
- Store GitHub Actions secrets using repository or environment-scoped secrets. Never echo secrets in workflow logs.
- Separate environment configuration (endpoints, resource names, capacity settings) from agent logic. Use the
/infra/environments/parameter files for this.
Auditability and Review
- Enforce pull request reviews for all changes to
/src/prompts,/src/agents, and/infravia CODEOWNERS. - Require status checks to pass before merging. Blocked merges prevent untested changes reaching production.
- GitHub's workflow run history gives you a complete deployment audit trail. You can answer "what was deployed to prod on Tuesday and who approved it" in seconds.
- For regulated environments, consider branch protection rules that require signed commits.
Safe Rollout
- Use canary or blue-green patterns where Foundry supports them for high-traffic agents.
- Always keep the previous image tag available in the registry. Do not delete images on deployment.
- Document and test your rollback procedure before you need it in production.
Observability and Operational Readiness
A deployed agent that you cannot observe is an agent you cannot operate. Build observability in from the start.
What to Monitor
- Deployment health - Track whether each Foundry deployment succeeded and the agent is responding. Wire deployment outcomes back to GitHub workflow run status.
- Model and tool errors - Log tool call failures, model timeout errors, and safety filter activations. Aggregate these in Azure Monitor or Application Insights.
- Latency - Track end-to-end response latency per agent version. A latency increase after a model or prompt change is an early signal of a quality regression.
- Token consumption - Monitor token usage per request and per session. Unexpected increases can indicate prompt injection or runaway orchestration loops.
- Traceability - Log which agent version handled each request. Correlation between the image tag and request traces is essential for debugging production issues.
Debugging and Alerting
- Use structured logging with a consistent schema. Include fields for agent version, session ID, tool called, and outcome.
- Set up alerts for error rate thresholds and latency percentiles. Alert before users notice the problem.
- For failed agent runs, ensure logs capture the full conversation context (within your data retention policy) so that developers can reproduce and diagnose the failure.
Microsoft Foundry Toolboxes
One of the most important additions to the Foundry platform is Toolboxes, currently in Public Preview. If you have ever seen an agent codebase where three different agents each wire the same search tool with their own credentials and slightly different configurations, you already understand the problem Toolboxes solve.
A Toolbox is a named, versioned bundle of tools managed centrally in Microsoft Foundry. You define the tools once, configure authentication and access centrally, and publish a single MCP-compatible endpoint. Any agent in any runtime consumes that endpoint without per-tool wiring, custom SDK integration, or duplicated credential management.
Figure: Before and after Foundry Toolboxes. Each agent previously managed its own tool connections. With Toolboxes, agents connect to one governed endpoint.
The Four Pillars
- Discover (coming soon) - Find approved tools without browsing long catalogues. Reduces duplication by surfacing what already exists before developers build something new.
- Build (available today) - Select tools into a named toolbox. Supported types include built-in tools (Web Search, Code Interpreter, File Search, Azure AI Search), MCP servers, Agent-to-Agent (A2A) endpoints, and OpenAPI-defined services.
- Consume (available today) - A single MCP-compatible endpoint exposes every tool in the toolbox to any agent runtime. Agents that can speak MCP can use a Foundry Toolbox without any Foundry-specific SDK dependency.
- Govern (coming soon) - Centralised authentication and observability applied to every tool call flowing through the toolbox. Security and platform teams get consistent controls without asking developers to bolt governance onto every agent individually.
Toolboxes and GitOps: A Natural Fit
Toolboxes are particularly well-suited to a GitOps delivery model because the toolbox definition is a discrete, versioned artefact. Instead of credentials and tool configuration scattered across agent codebases, the toolbox becomes its own managed entity with its own version history.
The key design property is that the toolbox endpoint URL is stable. When you promote a new toolbox version to be the default, agents consuming the endpoint pick up the update without any code changes. This means you can update tool configuration, add a new MCP server, or rotate credentials in the toolbox without redeploying every agent that uses it.
Figure: Toolbox versioning in a GitOps model. Commits trigger CI validation and deployment of new toolbox versions. The stable endpoint URL allows agents to consume updates without redeployment.
Adding a Toolbox to Your Repository
In your GitOps repository, toolbox definitions belong in /src/tools/toolbox_config.py or as a declarative configuration file checked into version control. The following example creates a toolbox that combines web search, Azure AI Search over internal documentation, and a GitHub MCP server:
# src/tools/toolbox_config.py
# Run this via CI to create or update a toolbox version in Foundry.
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
import os
client = AIProjectClient(
endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
credential=DefaultAzureCredential()
)
toolbox_version = client.beta.toolboxes.create_toolbox_version(
toolbox_name="customer-feedback-toolbox",
description="Tools for triaging customer feedback: search, docs, and GitHub.",
tools=[
{
"type": "web_search",
"description": "Search approved public documentation sites.",
"custom_search_configuration": {
"project_connection_id": os.environ["BING_CONNECTION_NAME"],
"instance_name": os.environ["BING_INSTANCE_NAME"]
}
},
{
"type": "azure_ai_search",
"name": "product-manuals-search",
"description": "Search internal product documentation.",
"azure_ai_search": {
"indexes": [
{
"index_name": os.environ["SEARCH_INDEX_NAME"],
"project_connection_id": os.environ["SEARCH_CONNECTION_ID"]
}
]
}
},
{
"type": "mcp",
"server_label": "github",
"server_url": "https://api.githubcopilot.com/mcp",
"project_connection_id": os.environ["GITHUB_CONNECTION_ID"]
}
],
)
print(f"Toolbox version created: {toolbox_version.version}")
print(f"MCP endpoint: {toolbox_version.mcp_endpoint}")
To promote a toolbox version to be the default (the endpoint agents use without specifying a version), add this to your deployment workflow:
# Promote toolbox version to default after validation
toolbox = client.beta.toolboxes.update(
toolbox_name="customer-feedback-toolbox",
default_version=toolbox_version.version,
)
print(f"Default version is now: {toolbox.default_version}")
The stable endpoint for agents consuming this toolbox is:
https://<your-project>.services.ai.azure.com/api/projects/<project>/toolbox/customer-feedback-toolbox/mcp?api-version=v1
Attaching the Toolbox to Your Hosted Agent
In your agent code, connect to the toolbox via a single MCP tool definition. The agent gains access to every tool in the toolbox without knowing their individual configurations:
# src/agents/agent.py (relevant excerpt)
from agent_framework import MCPStreamableHTTPTool
import httpx, os
toolbox_endpoint = os.environ["FOUNDRY_TOOLBOX_ENDPOINT"]
http_client = httpx.AsyncClient(
auth=_ToolboxAuth(token_provider), # Microsoft Entra bearer token
timeout=120.0,
)
mcp_tool = MCPStreamableHTTPTool(
name="toolbox",
url=toolbox_endpoint,
http_client=http_client,
load_prompts=False,
)
# Agent now has access to web search, AI Search, and GitHub MCP
# through one tool definition and one authenticated connection.
GitOps Workflow Extension for Toolboxes
Add a dedicated job to your build-deploy workflow to create and promote toolbox versions as part of the same CI/CD pipeline:
deploy-toolbox:
name: Deploy Toolbox Version
needs: validate
runs-on: ubuntu-latest
environment: dev
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Azure login (OIDC)
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Create toolbox version in Foundry
env:
FOUNDRY_PROJECT_ENDPOINT: ${{ vars.FOUNDRY_PROJECT_ENDPOINT_DEV }}
BING_CONNECTION_NAME: ${{ vars.BING_CONNECTION_NAME }}
BING_INSTANCE_NAME: ${{ vars.BING_INSTANCE_NAME }}
SEARCH_INDEX_NAME: ${{ vars.SEARCH_INDEX_NAME }}
SEARCH_CONNECTION_ID: ${{ vars.SEARCH_CONNECTION_ID }}
GITHUB_CONNECTION_ID: ${{ vars.GITHUB_CONNECTION_ID }}
run: python src/tools/toolbox_config.py
Key points to note:
- Toolbox configuration is Python code in source control, reviewed through pull requests like any other change
- Connection IDs and index names are environment variables from GitHub Actions variables, not hardcoded in the script
- The same script runs for dev, test, and prod with different environment variable bindings
- Toolbox version promotion is a separate step from agent deployment, so you can update tools independently of the agent container
- Because the toolbox endpoint is stable, rolling back a toolbox version does not require rolling back the agent image
Common Pitfalls
Teams adopting this pattern commonly make the following mistakes. Identifying them early saves significant operational pain later.
- Treating prompts as unmanaged text. If your system prompt lives in a portal text box rather than a versioned file, you have no history, no review process, and no rollback capability. Move prompts into source control on day one.
- Deploying manually from the portal. Even one manual deployment breaks the GitOps contract. Your repository no longer reflects the true state of the environment. Automate everything and remove portal deployment permissions from individuals.
- Mixing environment configuration into source files. Hardcoded endpoint URLs or model deployment names in
agent_config.jsonmean your dev and prod configurations diverge at the source level. Use parameter files and environment variables resolved at deployment time. - Poor separation between agent logic and tool logic. When agents and tools are tightly coupled in a single file, a tool change requires a full agent review and redeployment. Keep them separate so they can evolve independently.
- Not versioning your Toolbox definition. Defining a Foundry Toolbox interactively through the portal gives you no audit trail and no rollback path. The toolbox configuration script belongs in source control alongside your agent code.
- Skipping evaluation before promotion. Deploying a prompt change without running a structured evaluation against a representative test set is how regressions reach production. Build evaluation into the pull request workflow, not just the deployment workflow.
- No rollback plan. If your first rollback is unplanned and urgent, it will be slow and stressful. Test your rollback procedure in a non-production environment and document the steps.
- Ignoring token and cost signals. AI workloads have variable cost profiles. A change that doubles average token consumption per request may be functionally correct but economically unsustainable. Monitor consumption as a first-class signal.
Example GitHub Actions Workflow
The following workflow runs on pull request validation and on merge to main. It covers the core delivery lifecycle: validate, build, deploy to dev, and smoke test.
# .github/workflows/build-deploy.yml
name: Build and Deploy Foundry Hosted Agent
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
REGISTRY: myregistry.azurecr.io
IMAGE_NAME: my-foundry-agent
jobs:
validate:
name: Validate Agent Configuration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -r requirements.txt
- name: Validate agent config schema
run: python scripts/validate_agent.py
- name: Run unit tests
run: pytest tests/unit/ -v
- name: Lint code
run: ruff check src/
build:
name: Build and Push Container Image
needs: validate
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
id-token: write
contents: read
outputs:
image_tag: ${{ steps.meta.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Azure login (OIDC)
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Log in to Azure Container Registry
run: az acr login --name ${{ env.REGISTRY }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,format=short
- name: Build and push image
uses: docker/build-push-action@v7
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
deploy-dev:
name: Deploy to Foundry Dev
needs: build
runs-on: ubuntu-latest
environment: dev
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Azure login (OIDC)
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy agent to Foundry Dev project
run: |
az ai foundry agent deploy \
--project ${{ vars.FOUNDRY_PROJECT_DEV }} \
--image ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }} \
--environment dev
- name: Run smoke tests against dev
run: pytest tests/smoke/ -v --base-url ${{ vars.AGENT_URL_DEV }}
deploy-test:
name: Deploy to Foundry Test
needs: deploy-dev
runs-on: ubuntu-latest
environment: test
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Azure login (OIDC)
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_TEST }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy agent to Foundry Test project
run: |
az ai foundry agent deploy \
--project ${{ vars.FOUNDRY_PROJECT_TEST }} \
--image ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }} \
--environment test
- name: Run smoke tests against test
run: pytest tests/smoke/ -v --base-url ${{ vars.AGENT_URL_TEST }}
Key decisions in this workflow:
- Validation runs on every pull request, not just on merge. Fast feedback catches problems before review.
- The container image is built once and the image tag is passed forward to deployment jobs. The same artefact is promoted across environments.
- Authentication uses OIDC federated credentials via
azure/login@v3withid-token: writepermissions. No long-lived secrets are stored in GitHub for Azure authentication. - The
environment: testdirective in the deploy-test job triggers a GitHub environment approval gate. A named reviewer must approve before the job runs. - Smoke tests run after every deployment. A failed smoke test prevents further promotion.
Best Practices Checklist
Use this checklist when adopting the GitOps pattern for a Microsoft Foundry Hosted Agent:
- All agent artefacts, including prompts, tool definitions, model configuration, and Toolbox configuration scripts, are committed to source control
- No manual deployments to any environment; all changes flow through GitHub Actions workflows
- Pull request reviews are enforced for all changes to agent logic, prompts, and infrastructure via CODEOWNERS
- Unit tests cover tool logic; integration tests cover end-to-end agent behaviour; smoke tests cover deployed environments
- Container images are built once per commit and promoted across environments; images are not rebuilt per environment
- Environment configuration (endpoints, resource names) lives in parameter files, never in source code
- Secrets are stored in Azure Key Vault and accessed via managed identity at runtime
- GitHub environment approval gates control promotion from dev to test to prod
- Foundry Toolboxes are used to centralise tool definitions, credentials, and access governance across all agents; the toolbox configuration script is version-controlled and deployed through CI/CD
- Toolbox versions are promoted via the
update default_versionAPI step in the deployment workflow, not manually through the portal - Latency, error rate, and token consumption are monitored with alerting thresholds
- The rollback procedure is documented, automated, and has been tested in a non-production environment
- GitHub Issues are used to record the intent behind significant changes and link to the pull requests that implement them
- Branch protection rules prevent direct pushes to main and require status checks to pass before merge
- The previous image tag is retained in the registry and stored as a GitHub environment variable for rollback
Conclusion
A Microsoft Foundry Hosted Agent is not something you deploy once and forget. Prompts evolve, tools change, models are upgraded, and policy requirements shift. Every one of those changes has the potential to alter agent behaviour in ways that affect users, costs, and compliance posture.
GitOps, implemented through GitHub and GitHub Tasks, gives you the operational discipline to manage that complexity. Source control for all artefacts. Pull request review for every change. Automated validation, build, and deployment. Environment promotion gates. A complete audit trail from task to production. These are not bureaucratic overhead; they are the foundation of reliable, trustworthy AI agent operations.
The teams that operate AI agents well are the ones that treat them like production software from the start. The investment in pipeline, structure, and governance pays back every time a change goes smoothly, every time a rollback takes minutes rather than hours, and every time a security or compliance reviewer can answer their question from a pull request history rather than a support ticket.
Build the discipline in early. Your future self, and your production environment, will benefit from it.
References
- Microsoft Foundry documentation
- Microsoft Foundry Agent Service documentation
- Microsoft Foundry Toolboxes documentation
- Introducing Toolboxes in Foundry (Microsoft Developer Blog)
- GitHub Actions documentation
- GitHub Projects and Tasks documentation
- Azure Container Registry documentation
- Azure Key Vault documentation
- Microsoft Entra Managed Identities documentation
- OpenGitOps Principles