Skip to main content

Agent Integration

The Shift Platform is designed from the ground up to be consumed by AI coding agents as well as human developers. Every CLI command, API endpoint, and response format is structured for programmatic consumption.

Key Principles

  1. Structured output -- Use --json for machine-readable responses
  2. Semantic exit codes -- Use exit codes 0-5 for control flow without parsing text
  3. API key authentication -- Use X-API-Key header for non-interactive auth
  4. Standard response envelope -- Every API response follows { success, data } or { success, error }
  5. Batch operations -- Reduce round trips with batch endpoints

CLI: The --json Flag

Every CLI command supports --json for structured output. Agents should always use this flag:

# Human output (default)
shift-cli yp services list
# NAME TAGS SYSTEM
# payment-api payments, core billing-system

# JSON output (for agents)
shift-cli yp services list --json
# [{"id":"a1b2c3d4","name":"payment-api","tags":["payments","core"],...}]

The --quiet flag suppresses all stdout, leaving only the exit code:

shift-cli yp services get my-service --quiet
echo $? # 0 = exists, 4 = not found

Exit Codes for Control Flow

Agents can map exit codes directly to recovery strategies without parsing output:

Exit CodeConstantAgent Action
0EXIT_SUCCESSProceed with the result
1EXIT_ERRORLog error, escalate or retry
2EXIT_USER_ERRORFix command arguments and retry
3EXIT_NOT_INITIALIZEDRun initialization first, then retry
4EXIT_NOT_FOUNDCreate the missing resource, or adjust the query
5EXIT_CONNECTIONWait and retry, or check network configuration

Example: Conditional Resource Creation

# Check if a service exists, create it if not
shift-cli yp services get my-service --quiet 2>/dev/null
exit_code=$?

if [ $exit_code -eq 0 ]; then
echo "Service exists"
elif [ $exit_code -eq 4 ]; then
shift-cli yp services add --name my-service --language TypeScript --json
elif [ $exit_code -eq 5 ]; then
echo "Gateway unreachable, retrying..."
sleep 5
shift-cli yp services get my-service --quiet
fi

API: Response Envelope

Every API response uses the standard envelope format:

// Success
{
"success": true,
"data": { ... }
}

// Error
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Service not found"
}
}

Agents should always check the success field before accessing data.

Authentication for Agents

Agents should use API key authentication via the X-API-Key header:

curl -H "X-API-Key: $SHIFT_API_KEY" \
https://app.the-shift.dev/api/v1/catalog/services

Or with the SDK:

import { createClient } from "@the-shift/sdk";

const client = createClient({
gatewayUrl: "https://app.the-shift.dev",
apiKey: process.env.SHIFT_API_KEY,
});

The API key bypasses cookie/session authentication entirely, making it suitable for non-interactive agent workflows.

Batch Operations

For high-throughput scenarios, use batch endpoints to reduce round trips:

# Batch ingest analytics events
curl -X POST $GATEWAY_URL/api/v1/pulse/events/batch \
-H "Content-Type: application/json" \
-H "X-API-Key: $SHIFT_API_KEY" \
-d '{
"events": [
{"name": "file.created", "properties": {"path": "/src/App.tsx"}},
{"name": "file.created", "properties": {"path": "/src/index.ts"}},
{"name": "build.completed", "properties": {"duration": 1200}}
]
}'

Example Agent Workflow

Here is a complete agent workflow that registers a new service, sets up governance, and tracks the operation:

#!/bin/bash
set -e

API="https://app.the-shift.dev"
KEY="$SHIFT_API_KEY"

# 1. Register the service in Yellow Pages
SERVICE=$(curl -s -X POST "$API/api/v1/catalog/services" \
-H "Content-Type: application/json" \
-H "X-API-Key: $KEY" \
-d '{
"name": "user-service",
"description": "User management and profiles",
"tags": ["users", "auth"]
}')

SERVICE_ID=$(echo "$SERVICE" | jq -r '.data.id')
echo "Created service: $SERVICE_ID"

# 2. Classify sensitive fields in Ledger
curl -s -X POST "$API/api/v1/ledger/classifications" \
-H "Content-Type: application/json" \
-H "X-API-Key: $KEY" \
-d "{
\"service\": \"user-service\",
\"field\": \"user.email\",
\"level\": \"confidential\",
\"ppiCategory\": \"contact-info\"
}"

# 3. Create a retention policy
curl -s -X POST "$API/api/v1/ledger/policies" \
-H "Content-Type: application/json" \
-H "X-API-Key: $KEY" \
-d '{
"name": "user-data-90d",
"service": "user-service",
"retentionDays": 90,
"action": "anonymize"
}'

# 4. Track the provisioning event in Pulse
curl -s -X POST "$API/api/v1/pulse/events" \
-H "Content-Type: application/json" \
-H "X-API-Key: $KEY" \
-d "{
\"name\": \"service.provisioned\",
\"properties\": {\"serviceId\": \"$SERVICE_ID\", \"agent\": \"provisioner-v1\"}
}"

# 5. Emit an audit event in Ledger
curl -s -X POST "$API/api/v1/ledger/events" \
-H "Content-Type: application/json" \
-H "X-API-Key: $KEY" \
-d "{
\"action\": \"service.created\",
\"service\": \"user-service\",
\"resource\": \"$SERVICE_ID\",
\"actor\": \"provisioner-agent\",
\"details\": {\"automated\": true}
}"

echo "Service provisioning complete"

App-Scoped Studio Sessions

Studio sessions can be coupled to Stage apps for context-aware development. When a session is bound to an app, it gains:

  • Auto-seeding — Session files are pre-populated from the app's Stage files
  • App-scoped routing — Sessions are accessible at /studio/app/:appSid/:sessionSid
  • Filtered listingGET /api/v1/studio/sessions?appSid=<sid> returns only sessions for that app

Two Entry Modes

  1. New project — Create via intent + scaffold, which auto-links an appSid to the session
  2. Existing app — Open an app in Studio, which auto-seeds files from the app's Stage session

App Context Snapshots

Use shift-cli app sync-context to materialize platform service context into your app's .shift/state directory. This provides agents with up-to-date service metadata, skill bundles, and configuration without network calls during development.

# Sync all service context
shift-cli app sync-context

# Sync specific services only
shift-cli app sync-context --service stage --service palette

# Push to Stage with auto-sync
shift-cli app push ./src /app

Tips for Agent Authors

  • Always use --json when calling the CLI from agent code.
  • Check exit codes before parsing output -- a non-zero code means the output may not be valid JSON.
  • Use API keys rather than OAuth tokens for automated workflows.
  • Batch when possible -- the Pulse batch endpoint is significantly faster for bulk event ingestion.
  • Handle EXIT_CONNECTION (5) gracefully -- the gateway may be restarting during deploys.
  • Use ID-or-name resolution -- you can pass either the nanoid ID or the human-readable name to any endpoint that accepts an :id parameter.