Template shape
Create a.yml file in your registry templates directory. Define inputs in expects, run actions in steps, and return the final value from returns.
- Start every file with
type: action. - Use
tools.<integration>for the namespace. - Set
title,description,display_group,namespace, andnameindefinition. - Define inputs in
expects. - Build the action in
steps. - Return the final value from
returns.
Expressions
Use${{ }} for expressions.
Use inputs to read the inputs you defined in expects.
Use steps to read the result of an earlier step. After a step runs, its output is available at steps.<ref>.result.
Read an input
Read an earlier step result
Build one step from another
inputsstepsSECRETSVARSFN.*
Secrets
Declare what each template needs underdefinition.secrets (API keys, structured types, or OAuth). That list drives which credentials must exist for the action when the workflow runs. Use the same ${{ SECRETS... }} paths in args as in any other expression.
Use the same ${{ SECRETS... }} syntax as workflow actions.
Custom secrets (API keys, SSH, mTLS, CA bundles, and so on):
<provider_id>_oauth. The key is the provider ID in uppercase plus _USER_TOKEN or _SERVICE_TOKEN:
authorization_code:${{ SECRETS.<provider_id>_oauth.<PROVIDER_ID_UPPER>_USER_TOKEN }}client_credentials:${{ SECRETS.<provider_id>_oauth.<PROVIDER_ID_UPPER>_SERVICE_TOKEN }}
Python UDFs
Declare credentials in@registry.register(..., secrets=[...]).
RegistrySecret: static keys; setsecret_typetossh_key,mtls, orca_certwhen needed (secret types). Optional:optional,optional_keys.RegistryOAuthSecret: declares a dependency on an existing OAuth integration. Pass theprovider_idandgrant_typethat match the integration in your workspace (a mismatch — for example declaringauthorization_codewhen the integration usesclient_credentials— will not resolve).
secrets.get("<KEY>") (key only, e.g. GOOGLE_DRIVE_USER_TOKEN), not a SECRETS. path.
YAML
Underdefinition, set a secrets list (same validator as Python).
Custom (optional secret_type for structured secrets):
provider_id and grant_type must match an integration already configured in your workspace. Use ${{ SECRETS.<provider_id>_oauth.<TOKEN_KEY> }} in args. Set optional: true on an OAuth entry when it is not always required.
Example providers
Seeintegrations/google_drive.py and integrations/slack_sdk.py for UDFs that use OAuth credentials. See tracecat_registry/core/ssh.py for an ssh_key secret example.
For YAML templates, see microsoft_teams/send_message.yml (authorization_code), google_docs/create_document.yml (client_credentials), and microsoft_sentinel/.../get_alert_rule_template.yml (optional dual grant). See templates/tools/exa/search.yml for a simple API key template.
For the full list of built-in provider IDs, see tracecat/integrations/providers/__init__.py.
Limitations
- Template steps only support
ref,action, andargs. - Template steps run in order.
- Template steps do not support
run_if,for_each,join_strategy,start_delay,timeout, ormax_attempts. - Templates can call tools actions, other templates, and
core.script.run_python. Other platform actions are not supported inside templates. - If a later step fails, you do not get a final result with earlier step outputs. Keep templates short. In practice, do not build templates with more than 2 steps.