Feature/code deploy zip upload#8146
Conversation
Implements code-based deployment as a complementary mode to container deploy. Agents with code_configuration in agent.yaml are deployed via multipart ZIP upload instead of Docker/ACR, eliminating permission complexity.
Add deploy mode prompt (code vs container) to the init flow. When code deploy is selected, prompts for runtime, entry_point, and dependency_resolution, then generates agent.yaml with code_configuration and azure.yaml with language: python (no Docker).
There was a problem hiding this comment.
Pull request overview
This PR adds code-based deployment support for the azure.ai.agents extension by packaging agent source code into a ZIP and deploying hosted agents via a multipart ZIP upload flow (as an alternative to container/image-based deployment).
Changes:
- Added
code_configurationtoagent.yamlparsing and mapped it to a new code-based hosted agent API request definition. - Implemented ZIP packaging in the service target and a deploy path that uploads ZIP + metadata, with optional remote-build polling.
- Updated
azd ai agent initflow to let users choose code deploy vs container deploy and to generate appropriate project/service settings.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go | Adds code-deploy packaging (ZIP + SHA-256) and a deploy flow that uploads ZIP artifacts and polls remote builds. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/yaml.go | Introduces CodeConfiguration and wires it into the hosted agent definition model. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/map.go | Maps code_configuration to a code-based hosted agent API definition (and preserves existing container/image mapping). |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_api/operations.go | Adds multipart ZIP create/update operations for agents. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_api/models.go | Adds API models for code-based agent definitions and code configuration. |
| cli/azd/extensions/azure.ai.agents/internal/exterrors/codes.go | Adds a new internal error code for agent create/update failures. |
| cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go | Adds interactive deploy-mode selection and prompts for code deploy configuration; adjusts azure.yaml service creation accordingly. |
…aults - Fix gosec G304 warnings with nolint annotations for safe file reads - Fix gosec G104 by properly handling tmpFile.Close() errors - Fix gofmt formatting in excludeDirs map - Update runtime choices to python_3_12/3_11/3_13 per spec - Change --no-prompt deploy mode default to container (backward compat) - Change --no-prompt runtime default to python_3_12 - Align prompt labels with spec wording - Add container.resources + startupCommand to azure.yaml for code deploy
- Add .azure and .env/.env.* to ZIP exclusion list to prevent uploading secrets - Skip symlinks in WalkDir to avoid including files outside agent directory - Stream ZIP directly to temp file with io.MultiWriter for SHA-256, reducing memory usage - Clean up temp file on all error paths using deferred cleanup - Only fall back to create agent on 404; propagate auth/5xx/network errors - Use context-aware select/time.After in polling loop for responsive cancellation - Add dedicated CodeMissingCodeZipArtifact error code - Fix entry point auto-detection to use srcDir instead of cwd - Replace hardcoded multipart boundary with mime/multipart.Writer - Add unit tests for zipDeployRequest multipart format and headers
…deploy and set metadata Content-Type - Add PatchAgent call after code deploy create/update to apply agent_endpoint and agent_card fields (matching container deploy behavior) - Use CreatePart with explicit Content-Type: application/json for the metadata multipart part instead of CreateFormField - Update unit test to verify metadata part Content-Type header
- Add //nolint:gosec to os.ReadFile in init_from_code.go - Handle req.Body.Close() return value in test transport - Suppress Close/Remove errors in deferred cleanup with _ = - Add 'mypy' to cspell.yaml words list
Add deploy mode prompt (code vs container) to the template init flow, allowing users to choose code deploy when initializing from a template. Skip ACR configuration when code deploy is selected. Auto-derive startup command from entry_point for code deploy instead of prompting.
…switch - Default to Container (Docker) for backward compatibility - Use clearer labels: 'Container (Docker)' / 'Code deploy (ZIP upload)' - Remove code_configuration from agent.yaml when switching to container mode
When skipACR is true (code deploy mode), skip the configureAcrConnection call entirely to prevent prompting users for ACR configuration.
When running 'azd ai agent init' from a subdirectory with an existing agent.manifest.yaml, the addToProject function received targetDir='.' which wrote 'project: .' into azure.yaml. Since azure.yaml resolves paths relative to the project root, this caused the service to point to the wrong directory. Fix: resolve the actual relative path from project root to cwd when targetDir is '.', so azure.yaml gets the correct project path (e.g. 'src/hello-world-python-invocations' instead of '.').
therealjohn
left a comment
There was a problem hiding this comment.
@v1212 is there anything we can do to check for supported regions if the code deploy option is selected?
What happened before was folks would choose a region supported by hosted agents, but then these features would fail because they were only available in a further subset of regions.
|
@v1212 When I selected C#, it still gives me the options for Code Deploy and then shows Python runtimes: |
jongio
left a comment
There was a problem hiding this comment.
Looked through the ZIP upload code deploy path. @therealjohn's UX feedback and the Copilot comments cover the major items well. A few structural things I noticed on top of those:
-
Duplicated prompt logic - promptCodeConfiguration (method on InitFromCodeAction, line 915) and promptCodeConfigurationShared (standalone func, line 1162) in init_from_code.go are nearly identical. Same runtime/entry-point/dependency prompts with minor differences in
oPrompt handling. Should be one function. -
Repeated agent.yaml I/O - isContainerAgent() and isCodeDeployAgent() each read and unmarshal �gent.yaml from disk independently. Both get called from Package(), Publish(), and Deploy(), so the same file is parsed 3+ times per deploy cycle.
-
Go 1.26 convention - �rrors.As at line 1031 of service_target_agent.go should use �rrors.AsType per AGENTS.md.
-
Startup command derivation duplicated between init.go (lines 1604-1621) and init_from_code.go's �ddToProject.
- T1: Hide code deploy for non-Python projects (isPythonProject check) - T2: Add TODO for region validation in code deploy - T3: Reorder runtime list to 3.11, 3.12, 3.13 - T4: Update entry point prompt wording - T6: Add descriptions to bundled/remote_build choices - J1: Consolidate promptCodeConfig into single shared function - J3: Use errors.AsType[*azcore.ResponseError] per Go 1.26 - J4: Extract shared deriveStartupCommand helper - V1: Rename to 'Container Image (Docker)' / 'Source Code (ZIP upload)' - V2: Unify HostedAgentDefinition with custom JSON marshal/unmarshal - V4: Fix error message to reference 'azd package' - V5: Extract prepareDeploy/finalizeDeploy shared helpers - C1+C3: Verify ZIP exclusions (.azure, .env) and temp file cleanup
so far, there is no APIs for listing available regions for code deploy feature, service team confirmed the feature will be rolled out to all regions, so in short term, we confirmed with Santhosh and ADC team to apply a limited regions in this PR - Westus2, Canada central and Northcentralus |
dotnet support will be implemented in a separate PR soon, here non-python will only go to container option in this PR. |
… default Add region validation for code deploy at both init-time (filter project list) and deploy-time (fail early with clear error). Supported regions: westus2, canadacentral, northcentralus. Unify dependency_resolution fallback default to 'remote_build' to match --no-prompt behavior.
…ATION Move CodeDeployRegions to project.config.go as a shared exported var, referenced by both init filtering and deploy validation. Add explicit check for empty AZURE_LOCATION with actionable error message.
…rompt - Include service error code/message and x-request-id in remote build failure errors - Rename 'container resource allocation' prompt to 'Select resources (CPU and Memory)'
|
/check-enforcer override |


Summary
Adds code deploy (ZIP upload) support for hosted agents as an alternative to container-based deployment. This enables deploying Python agent source code directly without requiring Docker/ACR.
Init Flow: 5 Supported Paths
The deploy mode prompt appears in all init flows when a Python project is detected. For non-Python projects, the code deploy option is hidden and the container path is used automatically. Users can re-run
azd ai agent initat any time to switch between code and container modes. Template files (Dockerfile, etc.) are never deleted.1. New Project (Template) -> Container Deploy
2. New Project (Template) -> Code Deploy
3. Existing Code -> Container Deploy
4. Existing Code -> Code Deploy
5. Re-init with Existing Manifest (mode switch)
Deploy Path Changes
azd deploy): NewpackageCodeDeploy()creates a ZIP archive of agent source,deployHostedCodeAgent()uploads via multipart form-data POST with SHA-256 verification. Auto-detected fromcode_configurationinagent.yaml.Foundry-Features: CodeAgents=V1Preview,HostedAgents=V1Previewheader,x-ms-code-zip-sha256for integrity,dependency_resolutionfield (string enum).language: python(no docker block), but still includescontainer.resourcesandstartupCommandforazd ai agent runcompatibility..azure/,.env,.env.*,__pycache__/,.venv/,venv/,.git/,node_modules/,.mypy_cache/,.pytest_cache/,.pyc/.pyofiles, symlinks, andagent.yamlitself. Temp files are cleaned up on error viadefer os.Remove.Files Modified
init_from_code.gopromptDeployMode(),promptCodeConfig()(consolidated from two near-duplicate functions),deriveStartupCommand()(shared helper),isPythonProject()(gates code deploy visibility)init.gopromptDeployModewithisPythonProjectcheck), skip ACR for code deploy, uses sharedpromptCodeConfigandderiveStartupCommand, fixedaddToProject()path resolution for subdirectory re-initinit_foundry_resources_helpers.goconfigureFoundryProjectEnv/selectFoundryProjectacceptskipACRparamcodes.goCodeAgentCreateFailed,CodeMissingCodeZipArtifacterror codesmodels.goCodeConfigurationAPIstruct; unifiedHostedAgentDefinitionwith optionalImage(container) andCodeConfiguration(code) fields + customMarshalJSON/UnmarshalJSON(container usescontainer_protocol_versions, code usesprotocol_versions)models_test.goHostedAgentDefinitionJSON marshalingoperations.goCreateAgentFromZip,UpdateAgentFromZip,zipDeployRequestoperations_test.gomap.goCreateHostedAgentAPIRequestuses unifiedHostedAgentDefinitionfor both code and container pathsmap_test.goHostedAgentDefinitionandProtocolVersionsfieldyaml.goCodeConfigurationstructservice_target_agent.goisCodeDeployAgent(),packageCodeDeploy(),deployHostedCodeAgent(); extractedprepareDeploy()/finalizeDeploy()shared helpers to reduce duplication between container and code deploy;errors.AsTypeper Go 1.26cspell.yamlmypyto words listHow to Build
cd cli/azd/extensions/azure.ai.agents go build ./... go vet ./... azd x buildManual Test Steps
Prerequisites
gpt-4o) in your Foundry projectazdCLI installed, logged in (azd auth login)azd x build --cwd <repo>/cli/azd/extensions/azure.ai.agentsTest 1: Code Deploy with Remote Build
Test 2: Switch to Bundled (same project, re-init from subdirectory)
Test Results
All configurations passed (deploy + invoke verified):
Notes
azd deployreadsagent.yaml-- ifcode_configurationis present, code deploy; otherwise container deploy. No flags needed.skipACRparameter defaults tofalseat all existing call sites.azd ai agent initto switch modes. Template files (Dockerfile, .dockerignore) are never deleted.requirements.txtor.pyfiles). Non-Python projects default to container deploy. .NET code deploy support will come in a follow-up PR.--no-promptdefaults: Deploy mode -> container (backward compatible). Runtime ->python_3_12. Entry point ->main.py(orapp.pyif it exists in the source directory). Dependency resolution ->remote_build.postdeployhook looks up agent by azure.yaml service name instead of agent.yaml name, causing a 404 after successful deploy. Not related to this PR.Related
Spec: Azure/foundrysdk-specs#164 -- CLI spec for code deployment
Schema: microsoft/AgentSchema#96 -- add code_configuration to ContainerAgent schema
Fixes #7430