migrate-to-native
SkillDev tools[v2-only] Migrate a v2 connector app from Argo to native orchestration. For v3 migrations, use /upgrade-v3.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the migrate-to-native skill
What this skill tells your AI
The instructions your AI receives, as published by atlanhq/application-sdk in .claude/skills/migrate-to-native/SKILL.md and read by ahel’s review.
⚠ v2-only skill — NOT for
refactor-v3. This skill targets the Argo → native orchestration migration for v2 connectors. The classes, decorators, and directory layout referenced below (BaseSQLMetadataExtractionApplication,@activity.defn,get_workflow_args,app/activities/metadata_extraction/, etc.) do not exist on therefactor-v3branch — invoking this skill against a v3 codebase will fail. For v3 migrations, use/upgrade-v3instead.
Skill: Migrate App to Native Orchestration
You are helping migrate an Atlan connector app from Argo-based orchestration to native orchestration — where workflows run via Temporal through the Automation Engine instead of Argo Workflows.
Context
Read the full migration guide before starting:
- Migration guide: https://linear.app/atlan-epd/document/migrating-a-connector-app-to-native-orchestration-f0065f5675a5
- Sequence diagram (full flow): https://linear.app/atlan-epd/document/native-orchestration-sequence-diagram-cc3683aa8554
- Local copy:
docs/native-migration-guide.mdinapplication-sdk
Read the reference implementation:
atlan-redshift-app— the complete reference for all changes
The atlan-application-sdk base classes handle: connection normalization, hybrid credential resolution (inline + Vault), output path computation. Your job is to wire up the app-specific layer on top.
Instructions
Work through each section below in order. After each section, verify the change compiles or parses correctly before moving on.
Step 1 — Discover the app structure
Read these files to understand the current state:
app/handlers/{connector}.py— look forget_configmap,test_auth, credential handlingapp/activities/metadata_extraction/{connector}.py— look forget_workflow_args,_set_stateapp/workflows/metadata_extraction/{connector}.py— look forrun()return valueapp/templates/— check what template files exist (if any)pyproject.toml— check currentatlan-application-sdkrev/version
Identify:
- The connector name (used in file names and configmap IDs)
- Any connector-specific arg reshaping in
get_workflow_args - Whether
_set_stateis overridden - Whether
run()returns anything - Whether template files already exist
Step 2 — Update SDK dependency
In pyproject.toml, ensure atlan-application-sdk points to a commit that includes:
HandlerInterface._wrap_configmap()- Hybrid credential resolution in
BaseSQLMetadataExtractionActivities._set_state() BaseSQLMetadataExtractionWorkflow.run()returningDict[str, Any]
The minimum required commit is 75a48a934bf0b43751a63779879330e30f0028b8.
If the rev is older, update it and run uv lock to regenerate the lockfile.
Step 3 — Create credential form template
Create app/templates/atlan-connectors-{connector}.json.
This file defines the Config tab credential form. It must have:
"config"at the top level (no"id"or"name")- Hidden fields:
name,connector,connectorType - Visible connection fields:
host,port - Auth type radio:
auth-typewith enum values matching the connector's auth methods - Nested credential objects per auth type (e.g.
basic,iam,role) extranested object inside each auth type for connector-specific fields (database, deployment_type, etc.)anyOfarray to require the correct nested object based onauth-type
Use atlan-redshift-app/app/templates/atlan-connectors-redshift.json as the reference structure.
Step 4 — Create workflow form template
Create app/templates/workflow.json.
This file defines the Schedule tab workflow form. It must have:
- Top-level
"id": the connector name (e.g."redshift") - Top-level
"name": display name - Top-level
"logo": URL to connector logo config.propertieswith:connection— widget"connection"credential-guid— widget"credential",credentialType="atlan-connectors-{connector}"include-filter/exclude-filter— widget"sqltree"with"sql": "show atlan schemas"preflight-check— widget"sage"with connector-specific checks array- Any connector-specific params (extraction method, temp table regex, etc.)
config.stepswith at minimum:credential,connection,metadata
Use atlan-redshift-app/app/templates/workflow.json as the reference structure.
Step 5 — Update the handler
In app/handlers/{connector}.py, add or replace get_configmap:
@staticmethod
async def get_configmap(config_map_id: str) -> Dict[str, Any]:
base = Path().cwd() / "app" / "templates"
if config_map_id == "atlan-connectors-{connector}":
path = base / "atlan-connectors-{connector}.json"
else:
path = base / "workflow.json"
with open(path) as f:
raw = json.load(f)
return {ClassName}._wrap_configmap(config_map_id, raw)
Add import json and from pathlib import Path if not already present.
Remove any previous get_configmap implementation that read from Elasticsearch or K8s.
Step 6 — Slim down activities
In app/activities/metadata_extraction/{connector}.py:
Remove any _set_state override — the SDK handles both native (inline + Vault) and Argo (full Vault fetch) paths automatically.
Replace the full get_workflow_args override with a slim version that:
- Calls
await super().get_workflow_args(workflow_config) - Handles only connector-specific reshaping (e.g. flattening a
metadatadict) - Ensures
credentialis forwarded if present inworkflow_configbut not yet inworkflow_args
Example:
@activity.defn
async def get_workflow_args(self, workflow_config: Dict[str, Any]) -> Dict[str, Any]:
workflow_args = await super().get_workflow_args(workflow_config)
# Connector-specific: flatten metadata keys
metadata = workflow_args.get("metadata") or {}
for key, value in metadata.items():
if key not in workflow_args:
workflow_args[key] = value
if "credential" not in workflow_args and "credential" in workflow_config:
workflow_args["credential"] = workflow_config["credential"]
return workflow_args
Remove all imports that are no longer used after this change (e.g. SecretStore, get_workflow_id, DEPLOYMENT_NAME, build_output_path, etc.).
Step 7 — Update the workflow
In app/workflows/metadata_extraction/{connector}.py:
Change await super().run(workflow_config) to output_paths = await super().run(workflow_config) and return output_paths.
Remove any manual output path computation that was previously done in run() (the SDK now computes these from workflow_args["output_path"], workflow_args["output_prefix"], and workflow_args["connection"]).
Remove unused imports (json, Path, etc.) that are no longer needed.
Step 8 — Check if the manifest needs customisation
The SDK generates the app manifest automatically via BaseSQLMetadataExtractionApplication.get_manifest(). This produces a two-node DAG — extract (runs the connector's Temporal workflow) followed by publish (runs the Publish App) — covering the full extraction + publish pipeline. No manifest file needs to be created.
Check whether the default manifest covers the connector's needs:
- If all workflow form parameters map to the standard set (
connection,credential-guid,credential,include-filter,exclude-filter,temp-table-regex,extraction-method,advanced-config, etc.) → no change needed. - If the connector has additional form parameters that need to reach the Temporal workflow → override
get_manifest()to add them todag["extract"]["inputs"]["args"]. - If the connector needs a completely different DAG (e.g. no publish step, extra intermediate nodes) → return a fully custom dict from
get_manifest().
Example override for adding an extra parameter:
class MyConnectorApplication(BaseSQLMetadataExtractionApplication):
def get_manifest(self):
base = super().get_manifest()
base["dag"]["extract"]["inputs"]["args"]["my-extra-param"] = "{{my-extra-param}}"
return base
Step 9 — Verify type annotations
The SDK's WorkflowInterface.run() base method returns Optional[Dict[str, Any]]. Ensure your workflow's run() return type annotation matches: -> Dict[str, Any] (or Optional[Dict[str, Any]]).
Run the project's type checker if available:
uv run pyright app/
Fix any reported type errors before continuing.
Step 9 — Run linting and formatting
uv run ruff check app/ --fix
uv run ruff format app/
Re-stage any reformatted files before committing.
Step 10 — Verify locally
If local dev infrastructure is available (Dapr + Temporal), run the app and verify:
GET /workflows/v1/configmap/atlan-connectors-{connector}— returns credential form wrapped in{ success, message, data: ConfigMap }GET /workflows/v1/configmap/{connector}— returns workflow formPOST /workflows/v1/authwith a test credential — returns{ success: true }
Step 11 — Summary
After completing all steps, report:
- Files changed (list each file and the nature of the change)
- Files created (templates, manifest)
- Imports removed from activities
- Whether
_set_statewas present and has been removed - SDK version/rev that is now in use
- Any connector-specific logic that was preserved in
get_workflow_args - Any open questions or items that need manual review
What the SDK Handles (Do Not Re-implement)
- Connection normalization from AE entity object →
{ connection_qualified_name, connection_name } - Stripping sensitive fields from inline credential in production
- Fetching secrets from Vault via
SecretStore.get_secret(credential_guid) - Merging Vault secrets into the stripped inline credential
- Computing
transformed_data_prefix,publish_state_prefix,current_state_prefixfromoutput_path - Wrapping configmap response in
{ kind: ConfigMap, apiVersion, metadata, data } - Wrapping configmap in
{ success, message, data }server envelope
What Each App Must Implement
- Template JSON files (connector-specific form fields)
get_configmap()— file path routing byconfig_map_idget_workflow_args()— connector-specific arg reshaping onlyrun()— returnoutput_pathsfromsuper().run()- Manifest — SDK auto-generates the extract + publish DAG; override
get_manifest()only if the connector needs extra params or a different DAG shape
Signals
- GitHub stars
- 29
- Forks
- 17
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
migrate-to-native- Source
- github.com/atlanhq/application-sdk