Skip to Content

Starting a New Agentic Project

This guide lays out a new agent project on top of Ark and tests it end to end. It assumes the Quickstart is done — Ark is running and ark, kubectl work against your cluster.

Project Layout

Ark provides the runtime; your project — agents, tools, teams, queries — lives in its own directory (and usually its own repository). That separation lets each team evolve its agents independently of the platform.

There’s no required layout. The convention below is a starting point.

Prerequisites

  • Ark installed
  • kubectl configured
  • A model named default (ark models create default)
ark --version kubectl get pods -n ark-system kubectl get models

Step 1: Directory

mkdir -p my-agents/{agents,teams,queries,tools,mcp-servers} cd my-agents

From here, every resource is a YAML file you write and apply with kubectl.

Step 2: First Agent

cat > agents/customer-support.yaml <<'EOF' apiVersion: ark.mckinsey.com/v1alpha1 kind: Agent metadata: name: customer-support spec: description: Handles customer inquiries and support tickets modelRef: name: default prompt: | You are a helpful customer support assistant. Help users with their questions and issues professionally. EOF kubectl apply -f agents/customer-support.yaml kubectl get agent customer-support -o jsonpath='{.status.phase}' # ready

Step 3: Tool

An HTTP tool that calls the National Weather Service:

cat > tools/get-forecast.yaml <<'EOF' apiVersion: ark.mckinsey.com/v1alpha1 kind: Tool metadata: name: get-forecast spec: type: http description: Get weather forecast for a location and time period inputSchema: type: object required: ["office", "gridX", "gridY"] properties: office: type: string description: "Weather office identifier (e.g., TOP)" gridX: type: integer description: "Grid X coordinate" gridY: type: integer description: "Grid Y coordinate" http: url: https://api.weather.gov/gridpoints/{office}/{gridX},{gridY}/forecast EOF kubectl apply -f tools/get-forecast.yaml

See Tools for MCP, builtin, and agent-as-tool variants.

Step 4: Team

Pick a strategy — each one expects a slightly different shape. See Teams → Strategy walkthroughs for the full reference.

Sequential

Members run in declared order, one pass each:

apiVersion: ark.mckinsey.com/v1alpha1 kind: Team metadata: name: support-team-sequential spec: description: Triage, then specialist strategy: sequential members: - type: agent name: customer-support - type: agent name: order-tracker - type: agent name: escalation-handler

Sequential with Loops

Cycle through members until maxTurns is reached. loops: true and maxTurns must be set together:

apiVersion: ark.mckinsey.com/v1alpha1 kind: Team metadata: name: support-team-loops spec: description: Each member contributes in turn until maxTurns strategy: sequential loops: true maxTurns: 5 members: - type: agent name: customer-support - type: agent name: order-tracker

strategy: round-robin is deprecated and silently migrated to sequential with loops: true. Use the form above directly.

Selector

A nominated agent picks the next member. selector.agent and maxTurns are required. Loops are not allowed on selector teams. The selectorPrompt should instruct the agent to use the built-in select-next-speaker tool:

apiVersion: ark.mckinsey.com/v1alpha1 kind: Team metadata: name: support-team-selector spec: description: Selector agent picks the right specialist strategy: selector maxTurns: 10 members: - type: agent name: customer-support - type: agent name: order-tracker selector: agent: planner-agent selectorPrompt: | Choose the team member best suited to respond next. Available roles: {{.Roles}} Conversation history: {{.History}} Use the select-next-speaker tool to make your selection.

strategy: graph is deprecated and migrated to plain sequential with edges discarded. For graph-style routing inside a selector team, see Teams → Selector with graph.

Apply the chosen team:

kubectl apply -f teams/support-team-sequential.yaml kubectl get team support-team-sequential

Step 5: MCP Server (Optional)

Expose external capabilities via the Model Context Protocol:

cat > mcp-servers/example.yaml <<'EOF' apiVersion: ark.mckinsey.com/v1alpha1 kind: MCPServer metadata: name: example-mcp spec: address: value: "http://example-mcp.default.svc.cluster.local:8080/mcp" transport: http timeout: 1m EOF kubectl apply -f mcp-servers/example.yaml

For authentication and OAuth, see MCP Servers.

Step 6: Query

cat > queries/test-support.yaml <<'EOF' apiVersion: ark.mckinsey.com/v1alpha1 kind: Query metadata: name: test-support spec: input: "I need help with my order #12345" target: type: agent name: customer-support EOF kubectl apply -f queries/test-support.yaml

Watch it complete and inspect the response:

kubectl get query test-support -w # Phase: pending -> running -> done kubectl get query test-support -o jsonpath='{.status.response.content}'

Step 7: End-to-End Testing

Bash smoke script

cat > test-workflow.sh <<'EOF' #!/bin/bash set -e kubectl apply -f agents/ kubectl apply -f tools/ kubectl apply -f teams/ kubectl wait --for=jsonpath='{.status.phase}'=ready agent/customer-support --timeout=60s kubectl apply -f queries/test-support.yaml kubectl wait --for=jsonpath='{.status.phase}'=done query/test-support --timeout=120s RESPONSE=$(kubectl get query test-support -o jsonpath='{.status.response.content}') [ -n "$RESPONSE" ] || { echo "FAIL: empty response"; exit 1; } echo "PASS" echo "Response: $RESPONSE" kubectl delete query test-support EOF chmod +x test-workflow.sh ./test-workflow.sh

Declarative, repeatable tests via Chainsaw :

apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: customer-support-workflow spec: steps: - name: apply-resources try: - apply: file: agents/customer-support.yaml - apply: file: queries/test-support.yaml - name: wait-for-agent-ready try: - assert: resource: apiVersion: ark.mckinsey.com/v1alpha1 kind: Agent metadata: name: customer-support status: phase: ready - name: verify-query-done try: - assert: resource: apiVersion: ark.mckinsey.com/v1alpha1 kind: Query metadata: name: test-support status: phase: done (length(responses) > `0`): true (length(responses[0].content) > `10`): true - name: cleanup try: - delete: ref: apiVersion: ark.mckinsey.com/v1alpha1 kind: Query name: test-support

Run it:

chainsaw test --test-file chainsaw-test.yaml

Step 8: Iterate

Add agents as YAML files and apply the directory:

# agents/order-tracker.yaml, agents/product-recommender.yaml, ... kubectl apply -f agents/

Wire them into a richer team:

apiVersion: ark.mckinsey.com/v1alpha1 kind: Team metadata: name: full-support-team spec: description: Complete customer support workflow strategy: sequential members: - type: agent name: customer-support - type: agent name: order-tracker - type: agent name: escalation-handler

Best Practices

Organise by feature

my-agents/ ├── features/ │ ├── customer-support/ │ │ ├── agents/ │ │ ├── tools/ │ │ ├── queries/ │ │ └── tests/ │ └── order-processing/ │ ├── agents/ │ ├── tools/ │ └── tests/

Version control

git init git add . git commit -m "feat: initial Ark project setup"

Per-environment overlays with Kustomize

apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - agents/ - tools/ - teams/ namespace: my-agents-prod

Continuous testing in CI

name: Test Ark Agents on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup K3s run: curl -sfL https://get.k3s.io | sh - - name: Install Ark run: ark install -y - name: Run Tests run: chainsaw test --test-dir tests/

Troubleshooting

Agent stuck before ready

kubectl describe agent customer-support kubectl logs -n ark-system -l app=ark-controller kubectl get models

Query stuck

kubectl get query test-support -o yaml kubectl get query test-support -o jsonpath='{.status.error}' kubectl get events --field-selector involvedObject.name=test-support

Tool returns nothing

kubectl get tool get-forecast kubectl describe tool get-forecast

Next Steps

Last updated on