> ## Documentation Index
> Fetch the complete documentation index at: https://cadenya.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents and variations

> Create a draft agent and variation, publish it, dispatch an objective, and manage candidate configurations with the SDK.

An agent is a stable identity and lifecycle. A variation is the runnable configuration: prompt, model, constraints, discovery, compaction, and assignments. An objective snapshots one selected variation when it is created.

## What you need

Export:

```bash theme={null}
export CADENYA_API_KEY='your-api-key'
export CADENYA_WORKSPACE_ID='workspace_your-workspace-id'
export CADENYA_MODEL_ID='model_or_external_id_from_your_workspace'
```

Use [List models](/docs/api-reference/modelservice/list-models) to find an enabled model ID. The examples use a generated external ID for the agent, so replace `sdk-support-agent` if that value already exists in your workspace.

## Create the agent and its first variation

The API mirrors the dashboard boundary. Create the draft agent, then create a variation under it.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import Cadenya from '@cadenya/cadenya';

  const client = new Cadenya({
    apiKey: process.env['CADENYA_API_KEY'],
  });
  const workspaceId = process.env['CADENYA_WORKSPACE_ID']!;
  const modelId = process.env['CADENYA_MODEL_ID']!;

  const agent = await client.agents.create({
    workspaceId,
    metadata: {
      name: 'SDK Support Agent',
      externalId: 'sdk-support-agent',
    },
    spec: {
      description: 'Explains support options for a customer.',
      variationSelectionMode: 'VARIATION_SELECTION_MODE_RANDOM',
      systemPromptDataSchema: {
        type: 'object',
        properties: {
          company: { type: 'string' },
        },
        required: ['company'],
      },
    },
  });

  const variation = await client.agents.variations.create(
    agent.metadata.id,
    {
      workspaceId,
      metadata: {
        name: 'Baseline',
        externalId: 'baseline',
      },
      spec: {
        systemPromptTemplate:
          'You support {{ system_prompt_data.company }}. Answer in two or three sentences.',
        modelConfig: {
          modelId,
          temperature: 0.2,
        },
      },
    },
  );
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"log"
  	"os"

  	"go.cadenya.com/cadenya-go"
  	"go.cadenya.com/cadenya-go/option"
  	"go.cadenya.com/cadenya-go/shared"
  )

  func main() {
  	ctx := context.Background()
  	client := cadenya.NewClient(
  		option.WithWorkspaceID(os.Getenv("CADENYA_WORKSPACE_ID")),
  	)

  	agent, err := client.Agents.New(ctx, cadenya.AgentNewParams{
  		Metadata: shared.CreateResourceMetadataParam{
  			Name:       "SDK Support Agent",
  			ExternalID: cadenya.String("sdk-support-agent"),
  		},
  		Spec: cadenya.AgentSpecParam{
  			Description: cadenya.String(
  				"Explains support options for a customer.",
  			),
  			VariationSelectionMode: cadenya.AgentSpecVariationSelectionModeVariationSelectionModeRandom,
  			SystemPromptDataSchema: map[string]any{
  				"type": "object",
  				"properties": map[string]any{
  					"company": map[string]any{"type": "string"},
  				},
  				"required": []string{"company"},
  			},
  		},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	variation, err := client.Agents.Variations.New(
  		ctx,
  		agent.Metadata.ID,
  		cadenya.AgentVariationNewParams{
  			Metadata: shared.CreateResourceMetadataParam{
  				Name:       "Baseline",
  				ExternalID: cadenya.String("baseline"),
  			},
  			Spec: cadenya.AgentVariationSpecParam{
  				SystemPromptTemplate: cadenya.String(
  					"You support {{ system_prompt_data.company }}. Answer in two or three sentences.",
  				),
  				ModelConfig: cadenya.AgentVariationSpecModelConfigParam{
  					ModelID:     cadenya.String(os.Getenv("CADENYA_MODEL_ID")),
  					Temperature: cadenya.Float(0.2),
  				},
  			},
  		},
  	)
  	if err != nil {
  		log.Fatal(err)
  	}

  	log.Println(agent.Metadata.ID, variation.Metadata.ID)
  }
  ```

  ```ruby Ruby theme={null}
  require "cadenya"

  client = Cadenya::Client.new(api_key: ENV.fetch("CADENYA_API_KEY"))
  workspace_id = ENV.fetch("CADENYA_WORKSPACE_ID")

  agent = client.agents.create(
    workspace_id,
    metadata: {
      name: "SDK Support Agent",
      external_id: "sdk-support-agent"
    },
    spec: {
      description: "Explains support options for a customer.",
      variation_selection_mode: :VARIATION_SELECTION_MODE_RANDOM,
      system_prompt_data_schema: {
        type: "object",
        properties: {
          company: {type: "string"}
        },
        required: ["company"]
      }
    }
  )

  variation = client.agents.variations.create(
    agent.metadata.id,
    workspace_id: workspace_id,
    metadata: {
      name: "Baseline",
      external_id: "baseline"
    },
    spec: {
      system_prompt_template:
        "You support {{ system_prompt_data.company }}. Answer in two or three sentences.",
      model_config: {
        model_id: ENV.fetch("CADENYA_MODEL_ID"),
        temperature: 0.2
      }
    }
  )

  puts [agent.metadata.id, variation.metadata.id]
  ```
</CodeGroup>

The agent returns in `STATE_DRAFT`. Draft agents can be configured but reject objectives. The variation's Liquid template can read only from the `system_prompt_data` object supplied by each objective.

## Publish and run

An agent needs at least one variation before it can be published.

<CodeGroup>
  ```typescript TypeScript theme={null}
  await client.agents.publish(agent.metadata.id, { workspaceId });

  const objective = await client.objectives.create({
    workspaceId,
    agentId: agent.metadata.id,
    systemPromptData: {
      company: 'Acme',
    },
    firstUserMessage:
      'A customer cannot log in. What should they check first?',
  });

  console.log({
    objectiveId: objective.metadata.id,
    selectedVariation:
      objective.configSnapshot.agentVariation?.metadata.name,
  });
  ```

  ```go Go theme={null}
  _, err = client.Agents.Publish(
  	ctx,
  	agent.Metadata.ID,
  	cadenya.AgentPublishParams{},
  )
  if err != nil {
  	log.Fatal(err)
  }

  objective, err := client.Objectives.New(
  	ctx,
  	cadenya.ObjectiveNewParams{
  		AgentID: agent.Metadata.ID,
  		SystemPromptData: map[string]any{
  			"company": "Acme",
  		},
  		FirstUserMessage: cadenya.String(
  			"A customer cannot log in. What should they check first?",
  		),
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  log.Println(
  	objective.Metadata.ID,
  	objective.ConfigSnapshot.AgentVariation.Metadata.Name,
  )
  ```

  ```ruby Ruby theme={null}
  client.agents.publish(
    agent.metadata.id,
    workspace_id: workspace_id
  )

  objective = client.objectives.create(
    workspace_id,
    agent_id: agent.metadata.id,
    system_prompt_data: {
      company: "Acme"
    },
    first_user_message:
      "A customer cannot log in. What should they check first?"
  )

  puts [
    objective.metadata.id,
    objective.config_snapshot.agent_variation&.metadata&.name
  ]
  ```
</CodeGroup>

The create call returns immediately. `configSnapshot.agentVariation` identifies the configuration selected for this objective and remains unchanged if you edit the variation later.

## Create the agent and default variation atomically

Automation that already has the complete configuration can use `defaultVariation`:

```typescript theme={null}
const agent = await client.agents.create({
  workspaceId,
  metadata: {
    name: 'Atomic Agent',
    externalId: 'atomic-agent',
  },
  spec: {
    variationSelectionMode: 'VARIATION_SELECTION_MODE_RANDOM',
  },
  defaultVariation: {
    metadata: {
      name: 'Default',
      externalId: 'default',
    },
    spec: {
      systemPromptTemplate: 'Answer accurately and concisely.',
      modelConfig: { modelId },
    },
  },
});
```

The response still represents a draft agent. Publish it explicitly after creation.

## Add assignments

`addAssignment` accepts a discriminated union. The `type` field determines the one ID field that is allowed:

```typescript theme={null}
const assignment = await client.agents.variations.addAssignment(
  agent.metadata.id,
  variation.metadata.id,
  {
    workspaceId,
    type: 'toolSetId',
    toolSetId: 'external_id:faker-mcp',
  },
);

await client.agents.variations.removeAssignment(
  agent.metadata.id,
  variation.metadata.id,
  assignment.id!,
  { workspaceId },
);
```

The returned `assignment.id` identifies the assignment row. Keep it when your application needs to remove the relationship later.

See [Assign tools, memory, and sub-agents](/docs/guides/agents/assignments) for the `toolId`, `subAgentId`, and memory-layer variants.

## Add candidates and control selection

Create more variations under the same agent. When an objective omits `variationId`, the agent's mode chooses:

* `VARIATION_SELECTION_MODE_RANDOM` gives every variation equal probability.
* `VARIATION_SELECTION_MODE_WEIGHTED` uses Thompson Sampling over objective feedback. The dashboard calls this **Feedback Driven**.

Pin a controlled run by passing one variation:

```typescript theme={null}
const pinned = await client.objectives.create({
  workspaceId,
  agentId: agent.metadata.id,
  variationId: variation.metadata.id,
  systemPromptData: {
    company: 'Acme',
  },
  firstUserMessage: 'Run this exact candidate.',
});
```

Pinning overrides the selection mode. Feedback submitted for the objective is attributed to the snapshotted variation.

## Lifecycle actions

State is output-only. Use explicit actions:

```typescript theme={null}
await client.agents.publish(agent.metadata.id, { workspaceId });
await client.agents.unpublish(agent.metadata.id, { workspaceId });
await client.agents.archive(agent.metadata.id, { workspaceId });
await client.agents.unarchive(agent.metadata.id, { workspaceId });
```

Archiving hides the agent from normal lists and pauses its active schedules. Unarchiving returns it to draft, so publish it again before dispatching another objective.

<CardGroup cols={2}>
  <Card title="Configure variations" icon="code-branch" href="/docs/guides/agents/variations">
    Understand snapshots, automatic sampling, and explicit pinning.
  </Card>

  <Card title="Optimize with feedback" icon="chart-line" href="/docs/guides/agents/feedback-and-sampling">
    Update a candidate's posterior and inspect the next sampled objective.
  </Card>

  <Card title="Run objectives with the SDK" icon="bullseye" href="/docs/guides/sdk/objectives">
    Stream events, continue conversations, approve tools, and submit scores.
  </Card>

  <Card title="Use your own IDs" icon="fingerprint" href="/docs/guides/use-your-own-ids">
    Address resources with stable `external_id:` references.
  </Card>
</CardGroup>
