Waiting for engine...
Skip to main content

Custom Provider Lifecycle

This guide walks through the full lifecycle of a Custom Provider in the using the Custom Accounts GraphQL APIs in Agent Control Tower:

  1. Creating the provider account
  2. Creating an agent (with its automatic draft version and alias)
  3. Configure the DRAFT version
  4. Creating a version and alias of an agent
  5. Query and list operations
  6. Deleting a provider

All field names below are the exact GraphQL mutation and query names exposed by this service, verified against the generated schema at target/schema.graphql.

Terminology

What you might call itWhat it actually is in the API
"Provider" (the thing you create)AiAgentProviderAccount (providerType: CUSTOM, providerSubType: CUSTOM_PROVIDER or a named framework)
AiAgentProvider (singular, no "Account")Not something you create. It's a static, read-only rollup row per AiAgentProviderType, used only for dashboard counts (aiAgentProviders / aiAgentSubProviders). Ignore it for lifecycle purposes.
"Instruction"Not a separate entity. It's a [String] field directly on AiAgentTask (instructions).
"Packaged version"Not a separate mutation. It's a side effect of aiAgentAliasCreate when you omit agentVersionId — refer to Step 4.

Entity relationship

AiAgentProviderAccount (the "Custom Provider")
└─ AiAgent (1 : many)
└─ AiAgentVersion (1 : many — exactly one is the mutable DRAFT; all others are
immutable numbered packages: v1, v2, …)
└─ AiAgentAlias (1 : many — every agent always has exactly one alias
pointing at its DRAFT version)

AiAgentTask, AiAgentTool, AiAgentLlm, AiAgentGuardrail
are top-level entities scoped to providerAccountId, linked to a VERSION
(specifically an agent's DRAFT version) via association fields — NOT owned by it.

AiAgentTool → associates only to AiAgentTask (via aiAgentTaskIds)
"Instructions" → lives only on AiAgentTask (via instructions: [String!])

End-to-end example call sequence

  1. aiAgentProviderAccountCreateproviderAccountId
  2. aiAgentCreateagentId (DRAFT version and default alias auto-created)
  3. aiAgentTaskCreatetaskId (instructions inline, agentIds: [agentId])
  4. aiAgentToolCreatetoolId (aiAgentTaskIds: [taskId])
  5. aiAgentLlmCreatellmId (agentIds: [agentId])
  6. aiAgentGuardrailCreateguardrailId (agentIds: [agentId])
    • Iterate on the draft as needed (aiAgentTaskUpdate, aiAgentToolUpdate, and so on).
  7. aiAgentAliasCreate (no agentVersionId) → packages the draft into v1 plus a new alias
    • Keep editing the draft, and take another packages later with a second aiAgentAliasCreate.

Step 1: Create the Custom Provider

StepMutationKey inputs
CreateaiAgentProviderAccountCreateproviderType: CUSTOM (required), providerAccountName (required), providerSubType (optional, defaults to CUSTOM_PROVIDER), providerAccountDescription, metadataJson, externalAccountId

Returns an AiAgentProviderAccount. Save its id, you need it as providerAccountId for every entity you create in the steps below (agent, task, tool, LLM, guardrail).

note

providerType is immutable after create.

Step 2: Create the agent

StepMutationKey inputs
CreateaiAgentCreateproviderAccountId (required, from Step 1), agentName (required), agentDescription, tags, trustLevel (default UNENDORSED), metadata

On creation, the service automatically creates a DRAFT version and a default draft alias (informally the "TestAlias") there is no separate call needed. Tags and trust level passed here apply to the draft alias.

At this point you have:

  • AiAgent.id
  • AiAgent.agentVersions[0] → the DRAFT version (mutable — keep editing it in Step 3)
  • That version's default alias (TestAlias)

Step 3: Configure the DRAFT version

Everything in this step attaches to the agent's DRAFT version by passing agentIds: [ID!]. The service resolves each agent ID to its current DRAFT version internally. Keep editing the draft freely.

The DRAFT version is untouched and stays open for further edits. You can create a non-editable packaged version by referring to Step 4.

Setting up tasks and its instructions

StepMutationKey inputs
CreateaiAgentTaskCreateproviderAccountId (required), name (required), description, taskMetaData, instructions: [String!], agentToolIds: [ID!] (attach existing tools), agentIds: [ID!] (attach to agents' DRAFT versions), tags
UpdateaiAgentTaskUpdateid (required), name, description, taskStatus, taskMetaData, instructions: [String!] (wholesale replace), agentToolIds (incremental add), agentIds (incremental add), tags
Remove agent associationaiAgentTaskDisassociationid (required), agentIds (omit or leave empty to remove all)
DeleteaiAgentTaskDeleteid. Deleting a task fails if any association still exists.
note

There is no dedicated instruction-association mutation. instructions is a plain string list you set or replace directly on the task.

Setting up tools

A tool is associated to a task purely through the aiAgentTaskIds field on create or update. There is no separate "associate" mutation, only a dedicated aiAgentToolDisassociation to remove it. The schema explicitly deprecated a generic aiRegistryEntityType / aiRegistryEntityIds mechanism.

note

Tools can be associated only with a task, there is no need of a different entity type.

StepMutationKey inputs
CreateaiAgentToolCreateproviderAccountId (required), toolType (required), name (required), description, toolJson, resources: [AiAgentToolResourceInput!], aiAgentTaskIds: [ID!] (associate to task(s)), tags
UpdateaiAgentToolUpdateid (required), name, description, toolJson, status, resources, tags, aiAgentTaskIds (incremental add)
Remove task associationaiAgentToolDisassociationid (required), aiAgentTaskIds: [ID]! (pass an empty array to remove from all tasks)
DeleteaiAgentToolDeleteid. Tool deletion fails if any association exists.

Setting up LLMs

StepMutationKey inputs
CreateaiAgentLlmCreateproviderAccountId (required), name (required), description, agentIds (associate to DRAFT versions)
UpdateaiAgentLlmUpdateid (required), name, description, agentIds (incremental add)
Remove associationaiAgentLlmDisassociationid (required), agentIds: [ID!]!
DeleteaiAgentLlmDeleteid. You can only delete a DRAFT-version LLM

Setting up Guardrails

StepMutationKey inputs
CreateaiAgentGuardrailCreateproviderAccountId (required), name (required), description, configurationJson, agentIds (associate to DRAFT versions), tags
UpdateaiAgentGuardrailUpdateid (required), name, description, configurationJson, status, agentIds (incremental add), tags
Remove associationaiAgentGuardrailDisassociationid (required), agentVersionIds: [ID!]! (pass an empty array to remove all)
DeleteaiAgentGuardrailDeleteid — fails if any association exists

Step 4: Creating a version and alias of an agent

There is no dedicated "packaging" mutation. Call aiAgentAliasCreate with agentId and name, and omit agentVersionId:

aiAgentAliasCreate(input: {
agentId: "agent-guid",
name: "Production Alias"
}) {
id
name
agentVersion { id version }
}

When you omit agentVersionId, the service:

  1. Loads the agent's current DRAFT version.
  2. Allocates the next numeric version (v1, v2, …) and clones the version's core fields into a new immutable AiAgentVersion (agentStatus = ACTIVE).
  3. Copies the draft's LLM, guardrail, task and tool associations, tags, and instructions into the new version.
  4. Creates the new alias pointing at this freshly packaged version.

The DRAFT version is untouched and stays open for further edits. You can keep configuring tasks, tools, LLMs, and guardrails on it and create another package later.

If you instead pass an existing non-DRAFT agentVersionId, aiAgentAliasCreate creates an additional alias against that already published version and a new package is not created. Passing a DRAFT version ID is an error.

Managing versions and aliases

StepMutationKey inputs
Update aliasaiAgentAliasUpdateid, name, description, trustLevel, agentStatus, tags
Delete aliasaiAliasDeleteid — deleting the DRAFT/default alias deletes the whole agent; deleting a packaged alias deletes just that alias (and its version too, if left with no aliases)
Bulk delete aliasesaiAliasesDeleteaiAgentsWithAliases: [AgentWithAliasesInput!]!

Step 5: Query and list operations

QueryParamsReturns
aiAgentProviderAccountspageIndex, pageSize, aiAgentProviderType, accountName, providerSubTypePaginated list of provider accounts
aiAgentProviderAccountidSingle account, including agents[]
aiAgentspageIndex, pageSize, providerAccountIds, agentIdsPaginated list of agents
aiAgentByVersionIdaiAgentVersionIdAgent looked up via one of its versions
aiAgentListingsoffset, limit, providerAccountIds, searchInput, agentListingFilterDenormalized grid view (one row per alias/version) plus status counts
aiAgentListingFilterValuesfilter inputFilter-dropdown values (providers, models, tags, trust levels)
aiAgentTaskidSingle task
aiAgentTasksproviderAccountId (required), pageIndex, pageSizePaginated list of tasks
aiAgentToolidSingle tool
aiAgentToolsproviderAccountId (required), pageIndex, pageSizePaginated list of tools
aiAgentLlmidSingle LLM
aiAgentLlmsstartIndex, endIndex, providerAccountIdPaginated list of LLMs
aiAgentGuardrailidSingle guardrail
aiAgentGuardrailsstartIndex, endIndex, providerAccountIdPaginated list of guardrails
aiAgentAliasesproviderTypes, providerAccountIds, providerSubTypesAlias list for filter dropdowns
aiAgentTagsnoneDistinct tag keys in use
note

Versions and aliases don't have a standalone paginated query. Navigate them through AiAgent.agentVersions[].agentAliases[], or jump straight to a version or alias with aiAgentByVersionId.

Step 6: Delete the provider

StepMutationNotes
Delete agentaiAgentDeleteResults in deletion of the agent plus all its versions, aliases, and associations. Shared entities (tasks, tools, LLMs, guardrails) are only deleted if not used by another agent.
Bulk delete agentsaiAgentBulkDeleteids: [ID!]!
Delete provider accountaiAgentProviderAccountDeleteid

Delete agents (and their orphaned tasks, tools, LLMs, and guardrails) before deleting the provider account.

On this Page