Run the connector fleet quickstart In this tutorial, you will start the repository's deterministic connector-fleet topology and route one signed AIP action from aipctl, through a product-neutral aipd gateway, to a standalone Cal.diy connector host. The provider is a controlled local fixture, so the exercise needs no external Cal account or product credential. This is a learning path for the fleet process boundary. It is not a production deployment or a qualification run. The reviewed source is commit 97be86e9efedf07ecf1783b03800f683f107fb04. What you will observe By the end of the tutorial, you will have observed: • source-derived container image and connector release identities; • registry admission before a connector host starts; • two product-neutral gateway replicas and one lifecycle control plane; • one healthy Cal.diy connector replica for tenant-acme; • a signed call to cap:caldiy:profile.get with status completed; • durable action lookup through either gateway replica; • bounded removal of only the named tutorial stack and its volumes. The reference Compose file also defines deterministic hosts for Hermes Agent, Chatwoot, Dify, and CrewAI. This tutorial builds those images but starts only the Cal.diy product path. Twenty is one of the six maintained connectors, but it has no service in this deterministic fixture and follows its own deployment and qualification path. Prerequisites You need: • a clean checkout at the reviewed source revision; • Docker Engine with Docker Compose v2 and BuildKit; • enough local CPU, memory, and disk for a source-based multi-image build; • TCP port 18443 free on the loopback interface; • a POSIX-compatible shell and lsof for the port preflight. Run every command from the aip-core repository root. The first preparation can take substantially longer than the native quickstart because it builds the gateway, control plane, fixtures, and five product-host images. The Compose project has the fixed name aip-connector-fleet-qualification. Do not use this tutorial while another run is using that project or while its volumes contain evidence you need to retain. 1. Verify the source and Docker boundary Confirm the exact source revision, a clean worktree, and an available Docker daemon: export AIPSOURCEREVISION=97be86e9efedf07ecf1783b03800f683f107fb04 test "$(git rev-parse HEAD)" = "$AIPSOURCEREVISION" test -z "$(git status --porcelain)" docker info >/dev/null docker compose version All four checks must exit with status 0. If the worktree is not clean, use a separate clean checkout instead of hiding changes: the preparation script derives image and release identities from the complete workspace content. Check that the fixed host port is unused: if ! command -v lsof >/dev/null; then echo "lsof is required for the port preflight" >&2 exit 1 fi if lsof -nP -iTCP:18443 -sTCP:LISTEN | grep -q .; then echo "Port 18443 is already in use" >&2 exit 1 fi Expected result: the command prints nothing and exits with status 0. 2. Prepare source-derived images Build the exact images and write their immutable image IDs to the generated Compose environment: ./deploy/connector-fleet/prepare.sh test -s deploy/connector-fleet/.env.qualification Expected result: the script ends with a line beginning connector fleet preparation: PASS. The generated file contains source, image, and release metadata for this workspace. At the reviewed revision it does not contain product credentials. Define a short shell helper for the remaining commands: compose() { docker compose \ --profile products \ --env-file deploy/connector-fleet/.env.qualification \ -f deploy/connector-fleet/compose.yml \ "$@" } Inspect the fixed Compose project before changing it: compose ps --all If this lists containers from another investigation or qualification run, stop here and preserve that run first. This tutorial deliberately does not rename the project because the source-owned volume and evidence tooling use its fixed identity. 3. Start one product path Start the Cal.diy host and its declared dependencies, and wait for running services to become healthy: compose up --detach --wait --wait-timeout 300 cal-acme-a Expected result: the command exits with status 0. Compose runs short-lived initializers and admission jobs before it reports the long-running services as healthy. The dependency graph starts: • PostgreSQL and registry initialization; • deterministic identity, policy, secret, and product fixtures; • the connector lifecycle control plane; • the TLS edge; • aipd and aipd-b against shared durable state; • the controlled product upstream; • cal-acme-a as a standalone connector host. The setup graph also creates qualification-only admission artifacts. They are internal test infrastructure, not additional public product connectors, and their host services are not part of this tutorial outcome. Inspect both completed setup jobs and running services: compose ps --all cal-acme-a, aipd, aipd-b, control-plane, edge, postgres, and product-upstream should be running and healthy. Initialization and admission services may be exited with status 0 because they are one-shot jobs. 4. Route one signed read Run aipctl inside the isolated fleet network. The command mounts the source-generated client key, gateway DID, and local TLS authority from the Compose volumes: compose run --rm --no-deps \ --entrypoint /usr/local/bin/aipctl \ -e AIPCTLNATIVEPRINCIPALID=service:aipctl:qualification-acme \ -e AIPCTLNATIVETRUSTDOMAIN=fleet.test \ -e AIPCTLNATIVESIGNINGSEEDFILE=/fleet-state/secrets/client-acme-signing-seed.hex \ -e AIPCTLNATIVEPEERDIDFILE=/fleet-state/public/gateway.did \ -e AIPCTLNATIVETLSCAFILE=/caddy-data/caddy/pki/authorities/local/root.crt \ qualification action call \ https://aipd.fleet.test:8443 \ cap:caldiy:profile.get \ --action-id actconnectorfleetquickstart001 \ --input '{}' Expected result: the response is an AIP action result whose actionid is actconnectorfleetquickstart001 and whose status is completed. The output contains the deterministic Cal.diy profile returned by the controlled upstream. This completion demonstrates the configured local path: signed client request, gateway authentication, tenant-scoped capability routing, connector-host execution, and a product-shaped fixture response. It does not demonstrate behavior against a live Cal.diy deployment. 5. Read the action through the second gateway Query the shared durable action state through aipd-b without replaying the provider operation: compose run --rm --no-deps \ --entrypoint /usr/local/bin/aipctl \ -e AIPCTLNATIVEPRINCIPALID=service:aipctl:qualification-acme \ -e AIPCTLNATIVETRUSTDOMAIN=fleet.test \ -e AIPCTLNATIVESIGNINGSEEDFILE=/fleet-state/secrets/client-acme-signing-seed.hex \ -e AIPCTLNATIVEPEERDIDFILE=/fleet-state/public/gateway.did \ -e AIPCTLNATIVETLSCAFILE=/caddy-data/caddy/pki/authorities/local/root.crt \ -e AIPCTLNATIVEBEARERTOKENFILE=/fleet-state/secrets/native-bearer-token \ qualification action status \ https://aipd-b.fleet.test:8443 \ actconnectorfleetquickstart001 \ --include-result \ --include-receipts Expected result: the lifecycle view identifies the same action and capability, reports a terminal state with resultstatus set to completed, and includes the stored result. A successful lookup shows that the two gateway replicas use the same durable runtime state; it is not a failover or recovery test. 6. Verify the tutorial outcome Repeat a non-mutating status lookup and require both the connector host and gateways to remain healthy: test "$(compose ps --status running --services | grep -cx 'cal-acme-a')" -eq 1 test "$(compose ps --status running --services | grep -Ec '^aipd(-b)?$')" -eq 2 compose run --rm --no-deps \ --entrypoint /usr/local/bin/aipctl \ -e AIPCTLNATIVEPRINCIPALID=service:aipctl:qualification-acme \ -e AIPCTLNATIVETRUSTDOMAIN=fleet.test \ -e AIPCTLNATIVESIGNINGSEEDFILE=/fleet-state/secrets/client-acme-signing-seed.hex \ -e AIPCTLNATIVEPEERDIDFILE=/fleet-state/public/gateway.did \ -e AIPCTLNATIVETLSCAFILE=/caddy-data/caddy/pki/authorities/local/root.crt \ -e AIPCTLNATIVEBEARERTOKENFILE=/fleet-state/secrets/native-bearer-token \ qualification action status \ https://aipd.fleet.test:8443 \ actconnectorfleetquickstart001 \ --include-result >/dev/null All three commands must exit with status 0. You have now observed admission, registration, signed routing, standalone execution, and shared durable lookup for one low-risk product capability. Stop and clean up Before deletion, capture diagnostics if any step failed: compose ps --all compose logs --no-color --tail 200 aipd aipd-b control-plane cal-acme-a When no retained state from this named project is needed, remove its containers, network, and volumes: compose down --volumes --remove-orphans --timeout 30 test -z "$(compose ps --all --quiet)" The first command deletes the project volumes, including PostgreSQL state, generated keys, and any qualification evidence stored there. It does not prune unrelated containers, images, build cache, or volumes. Keep the images if you intend to repeat the tutorial; remove them only through a separately reviewed cleanup decision. Resolve common failures | Symptom | Decision | | Preparation reports that Docker is unavailable | Start or repair the Docker daemon, then rerun the same source check before preparation | | Port 18443 is already in use | Identify the owning process or existing fleet run; do not stop or delete it without confirming ownership | | An image build fails | Preserve the build output, confirm disk and tool availability, and rerun prepare.sh from the same clean revision | | A one-shot admission job exits nonzero | Inspect compose ps --all and that job's logs; do not bypass admission or start the host manually | | A service does not become healthy | Inspect the named service, its dependency state, and bounded logs before cleanup | | The signed action is rejected | Confirm that the command uses the generated principal, key, peer DID, CA, and tenant-acme fixture unchanged | | The action completes but the second lookup fails | Preserve gateway and PostgreSQL logs; this tutorial does not authorize recreating shared state as a repair | What happened internally The fixture generated trust material and immutable admission packages, migrated the connector registry, and admitted the Cal.diy connector version before its host process started. The host then registered a tenant-scoped replica and renewed its lease with the lifecycle control plane. The signed aipctl request reached the product-neutral gateway. The gateway selected an eligible Cal.diy replica from the registry and sent the action to the standalone host. That host resolved its fixture credential, called the controlled upstream, and returned a typed result. Both gateways used the same PostgreSQL-backed runtime state, so the second gateway could read the completed action without repeating the product call. The repository's full product-fleet qualification exercises all five fixture hosts, governed mutations, tenant isolation, durable replay, outages, restarts, and failover. Those checks belong to the qualification documentation and are intentionally outside this quickstart. Next steps • Understand connector-fleet architecture (../architecture/connector-fleet.md) • Adopt the Cal.diy connector (../connectors/cal-diy.md) • Deploy a connector fleet (../guides/deploy-connector-fleet.md) • Run connector-fleet qualification (../testing/connector-fleet-qualification.md) • Follow the separate Twenty path (../connectors/twenty.md)