Skip to main content

Migrating and duplicating content policies

Use the content policy migration tool to copy a policy—and its evaluation dataset and trained model, when applicable—from one DynamoAI environment to another, or to duplicate a policy within the same environment.

The tool runs in three modes:

ModePurpose
exportDownload policy metadata, dataset, and model info from the source API into a local folder (default ./policy_data, or --output-dir)
importRead that local folder and create or update a policy in the target environment from the saved JSON files
update-trainedAttach model weights at an S3 path so an imported policy is in a trained state (uses the target API only; no local export folder required)

For custom-trained policies, import with --import-model already performs the update-trained step. You do not run a separate third step in that case.

Files written by export (and read by import)

Export creates up to three JSON files under your output directory. Import expects the same files to be present (except finetuned_model.json is only required when using --import-model).

FileCreated whenContents
policy.jsonAlwaysPolicy definition: name, description, allowed/disallowed behaviors, moderation method, action, applicable direction (input/output), and related settings
dataset.jsonAlwaysGuardrail evaluation dataset: datapoints (prompts, compliance labels, review state), plus dataset metadata such as version and behavior lists
finetuned_model.jsonAlways (written on every export)Latest finetuned-model metadata from the source. If the policy has no trained model yet, export saves {}. When trained, includes fineTunedModelZipS3Path and isModelEncrypted. Required for import only when using --import-model

Note: Export does not download the weight archive itself—only the S3 path and metadata. Weights remain in object storage; import/--import-model or update-trained registers that path (or a new path you provide) on the target policy.

Example layout after export:

policy_data/
├── policy.json
├── dataset.json
└── finetuned_model.json # {} if policy is not trained yet

Use a dedicated folder per policy (recommended), for example ./policy_data/export_my_policy_<id>/, and pass the same path to import via --output-dir.

On export, the script fetches the full evaluation dataset with pagination (500 datapoints per page) and writes all three files. On import, it reads policy.json and dataset.json from --output-dir; it reads finetuned_model.json only when you pass --import-model.

Tool setup

Download the migration tool

Download these files into a working directory (for example content-policy-migration/):

FileDescription
script.pyMigration script (export, import, update-trained)
requirements.txtPython dependencies (requests, python-dotenv)
.env.exampleTemplate for API URLs and keys

Requirements

  • Python 3.6 or later
  • API access to the source and target environments:
    • Source: viewer access (or higher) to the policy you are copying
    • Target: DynamoGuard editor access (or higher) to create or update policies
  • URLs and API keys for both environments (they can be the same when duplicating within one deployment)

The script requires a .env file in the same directory as script.py. If .env is missing or any of the four variables below are unset, it exits before running.

Install dependencies

From the migration tool directory:

pip install -r requirements.txt

Configure credentials

Copy .env.example to .env and set values for the source and target environments:

SOURCE_VPC_URL=https://api.your-source.example
SOURCE_API_KEY=...
TARGET_VPC_URL=https://api.your-target.example
TARGET_API_KEY=...

When source and target are the same deployment, point both SOURCE_* and TARGET_* variables at that environment.

Quick reference: how many steps?

ScenarioSteps
Duplicate or copy within same environment (custom-trained)export → import --import-model
Copy to another environment; target can read source S3 weightsexport → import --import-model
Copy to another environment; weights must live in target storageexport → import → update-trained (target S3 path)
Default / out-of-the-box (OOB) policiesexport → import --default-policy (no model transfer)

Duplicating a policy in the same environment

When source and target are the same deployment, point both SOURCE_* and TARGET_* variables at that environment (and use an API key with the permissions above).

Model weights already live in that environment’s storage, so you can finish in two commands:

# 1. Export the policy you want to copy
python script.py --mode export --policy-id <POLICY_ID> \
--output-dir ./policy_data/my_policy_export

# 2. Import as a new policy, including trained weights
python script.py --mode import --import-model \
--output-dir ./policy_data/my_policy_export

The result is a new policy with the same configuration, dataset, and trained model.

Updating an existing policy (new version)

To refresh an existing policy instead of creating a duplicate, pass the target policy ID on import:

python script.py --mode import --import-model \
--target-policy-id <EXISTING_POLICY_ID> \
--output-dir ./policy_data/my_policy_export

This updates behaviors and description, syncs the dataset, and restores the trained state when --import-model is used.

With --target-policy-id, import does not create a new policy. It:

  1. Updates the guardrail definition (name, description, allowed/disallowed behaviors) via the target API.
  2. Incrementally syncs datapoints: unchanged points are skipped; only adds and deletes needed to match the export are applied (fewer unnecessary policy versions).

What import does (new policy vs. versioning)

Import pathBehavior
New policy (no --target-policy-id)Creates a policy and guardrail dataset on the target, sets the dataset stage to ready to train (approveReady), and uploads datapoints in batches of 500. For custom policies, methodParams uses a placeholder adapter path until --import-model or update-trained sets real weights. For OOB policies, use --default-policy to keep the original methodParams (adapter path).
Versioning (--target-policy-id)Updates config and incrementally syncs datapoints on the existing policy ID (see above).
--import-model (either path)After import, registers the S3 path and encryption flag from finetuned_model.json and marks the policy trained (same logic as update-trained).

update-trained (standalone) starts and cancels a training job on the target policy, then patches finetuned-model metadata with your S3 path and marks training complete. Use this when import ran without --import-model.

Copying between separate environments

Policy metadata and dataset

Always start with export on the source, then import on the target:

python script.py --mode export --policy-id <SOURCE_POLICY_ID> \
--output-dir ./policy_data/export_<name>

python script.py --mode import --output-dir ./policy_data/export_<name>

Without --import-model, the new policy is ready to train—configuration and datapoints are in place, but no trained weights are attached yet.

Model weights (custom-trained policies only)

Custom policies store finetuned weights in object storage (S3). Export saves the weight location in finetuned_model.json (fineTunedModelZipS3Path).

Same environment — You do not need to copy weights. Use --import-model on import.

Separate environments — Choose one approach:

  1. Shared or cross-account access — If the target deployment can read the source bucket/path, use import with --import-model. The tool registers the exported S3 path on the target policy.

  2. Isolated environments (recommended) — Copy the weight archive into storage that belongs to the target account (or a bucket the target can read). Then either:

    • Run import without --import-model, then update-trained with the new path, or
    • Edit finetuned_model.json to the new path before import with --import-model.
# Import dataset and config only
python script.py --mode import --output-dir ./policy_data/export_<name>

# Attach weights from the target environment's S3 path
python script.py --mode update-trained \
--policy-id <TARGET_POLICY_ID> \
--model-weights s3://target-bucket/path/to/weights.zip \
[--is-encrypted]

Use --is-encrypted if the weights file is encrypted.

Important: Do not run update-trained after import if you already used --import-model on that import. That flag runs the same trained-state update automatically.

When you use --import-model, the tool also sets whether the weights are encrypted from the source policy metadata saved at export time (isModelEncrypted in finetuned_model.json). You do not need (and cannot use) --is-encrypted on import — only on update-trained when you attach weights manually.

Default (out-of-the-box) policies

Built-in policies (for example Safety or Prompt Injection) use pre-installed model adapters in the moderation service. They do not have separate finetuned weight files to copy.

python script.py --mode export --policy-id <POLICY_ID> \
--output-dir ./policy_data/export_oob

python script.py --mode import --default-policy \
--output-dir ./policy_data/export_oob
  • Use --default-policy so adapter settings are preserved.
  • Do not use --import-model or update-trained for OOB policies.

The target environment must have the corresponding default adapters deployed for inference to work.

Command reference

Export

python script.py --mode export --policy-id <SOURCE_POLICY_ID> [--output-dir ./policy_data]
ArgumentRequiredDescription
--policy-idYesSource policy ID to export
--output-dirNoLocal folder for JSON files (default: ./policy_data)

Writes JSON files to the output directory. See Files written by export for details.

Import

python script.py --mode import [--output-dir ./policy_data] [--import-model]
python script.py --mode import --target-policy-id <TARGET_POLICY_ID> [--import-model]
FlagWhen to use
--output-dirFolder containing exported JSON (default: ./policy_data)
--import-modelTarget can use the exported S3 weight path; policy ends trained; isModelEncrypted copied from export (no --is-encrypted)
--target-policy-idUpdate an existing policy (new version) instead of creating a new one
--default-policyOOB / default policies only; preserves original methodParams

Update-trained (step 3 only)

python script.py --mode update-trained \
--policy-id <TARGET_POLICY_ID> \
--model-weights <S3_PATH> \
[--is-encrypted]
ArgumentRequiredDescription
--policy-idYesTarget policy ID (after import)
--model-weightsYesS3 URI of the weight archive the target can read
--is-encryptedNoSet if the weights file is encrypted

Use only when import was run without --import-model and you have a weight path the target environment can access. Does not read --output-dir.