Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tracecat.com/llms.txt

Use this file to discover all available pages before exploring further.

Tracecat makes it easy to turn your Python scripts into actions for agents and workflows. All you need is:
  • A single Python decorator, @registry.register
  • from typing import Annotated
  • from typing_extensions import Doc

Quick start

  1. Add a Python file to your custom registry package.
  2. Register one async function with @registry.register(...).
  3. Define typed inputs, read secrets with secrets.get(...), and return JSON-serializable data.
from typing import Annotated
from typing_extensions import Doc

from tracecat_registry import registry, RegistrySecret, secrets


# (Optional) Define secrets used in the function
secret_name = RegistrySecret(
    name="secret_name",
    keys=["SECRET_NAME"],
    optional_keys=["OPTIONAL_SECRET_NAME"],
)


# Register the function as a Tracecat UDF
@registry.register(
    default_title="Say goodbye secretly",
    description="This is a function that says goodbye",
    display_group="Greetings",
    namespace="integrations.greetings",
    # (Optional) Define secrets used in the function
    secrets=[secret_name],
)
async def say_goodbye_secretly(
    name: Annotated[str, Doc("The name to say goodbye to")],
):
    secret = secrets.get("SECRET_NAME")
    # We're returning the secret for demonstration only.
    # Do not do this in your own functions!
    return {"message": f"Goodbye, {name}! Secret: {secret}"}

What to define

  • Use tools.<integration> for the namespace.
  • Set default_title, description, display_group, doc_url, and namespace in @registry.register(...).
  • Define action inputs with type hints and Field(..., description=...).
  • Define required credentials with RegistrySecret(...) and pass them in secrets=[...].
  • Read secret values with secrets.get(...).
  • Return plain dicts, lists, strings, numbers, or booleans.

Declaring secret types

By default, secrets are custom (arbitrary key-value). If your action requires an SSH key, mTLS certificate, or CA certificate, set secret_type so the credentials UI renders the correct form.
secret_typeRequired keysDescription
"custom"AnyGeneric key-value pairs (default)
"ssh_key"["PRIVATE_KEY"]SSH private key (PEM)
"mtls"["TLS_CERTIFICATE", "TLS_PRIVATE_KEY"]mTLS client certificate and key
"ca_cert"["CA_CERTIFICATE"]CA certificate bundle

Examples

# SSH key secret — renders an SSH private key textarea in the UI
ssh_secret = RegistrySecret(
    name="ansible",
    keys=["PRIVATE_KEY"],
    secret_type="ssh_key",
)

# mTLS secret — renders certificate + key textareas
mtls_secret = RegistrySecret(
    name="mtls",
    keys=["TLS_CERTIFICATE", "TLS_PRIVATE_KEY"],
    secret_type="mtls",
    optional=True,
)

# CA certificate secret — renders a certificate textarea
ca_cert_secret = RegistrySecret(
    name="ca_cert",
    keys=["CA_CERTIFICATE"],
    secret_type="ca_cert",
    optional=True,
)

# Custom secret (default) — renders key-value inputs
api_secret = RegistrySecret(
    name="slack",
    keys=["SLACK_BOT_TOKEN"],
)
secret_type uses snake_case everywhere — Python declarations, the API, and the UI all use the same values (ssh_key, ca_cert, mtls, custom). Use the same ${{ SECRETS... }} syntax as workflow actions. Custom secrets (API keys, SSH, mTLS, CA bundles, and so on):
${{ SECRETS.<secret_name>.<KEY> }}
OAuth tokens live under <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 }}
${{ SECRETS.slack_oauth.SLACK_USER_TOKEN }}
${{ SECRETS.google_docs_oauth.GOOGLE_DOCS_SERVICE_TOKEN }}
Optional fallback when either grant type is allowed:
${{ SECRETS.microsoft_sentinel_oauth.MICROSOFT_SENTINEL_USER_TOKEN || SECRETS.microsoft_sentinel_oauth.MICROSOFT_SENTINEL_SERVICE_TOKEN }}

Python UDFs

Declare credentials in @registry.register(..., secrets=[...]).
  • RegistrySecret: static keys; set secret_type to ssh_key, mtls, or ca_cert when needed (secret types). Optional: optional, optional_keys.
  • RegistryOAuthSecret: declares a dependency on an existing OAuth integration. Pass the provider_id and grant_type that match the integration in your workspace (a mismatch — for example declaring authorization_code when the integration uses client_credentials — will not resolve).
Read values with secrets.get("<KEY>") (key only, e.g. GOOGLE_DRIVE_USER_TOKEN), not a SECRETS. path.
from tracecat_registry import RegistryOAuthSecret, RegistrySecret, registry, secrets

api = RegistrySecret(name="exa", keys=["EXA_API_KEY"])

oauth = RegistryOAuthSecret(
    provider_id="google_drive",
    grant_type="authorization_code",
)

YAML

Under definition, set a secrets list (same validator as Python). Custom (optional secret_type for structured secrets):
definition:
  secrets:
    - name: exa
      keys: ["EXA_API_KEY"]
    - name: ansible
      keys: ["PRIVATE_KEY"]
      secret_type: ssh_key
OAuth:
definition:
  secrets:
    - type: oauth
      provider_id: microsoft_teams
      grant_type: authorization_code
The 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

See integrations/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.

Example actions

You can browse all open-source integrations in Tracecat in tools actions. Use template actions to see how actions are composed, and use core actions to inspect built-in implementations. For concrete examples, browse the Slack, AWS Boto3, and FalconPy integrations.