Skip to content

Architecture overview

Ark is structured as a gateway that bridges two systems: Slack (via Socket Mode WebSocket) and AWS Bedrock (via the InvokeAgent streaming API).

Component diagram

┌─────────────────────────────────────────────────────┐
│                      Ark Gateway                     │
│                                                      │
│  ┌──────────────┐   ┌────────────┐   ┌───────────┐ │
│  │ Socket Mode  │──>│  Gateway   │──>│  Bedrock   │ │
│  │ (WebSocket)  │   │ (router)   │   │  Agent     │ │
│  └──────────────┘   └─────┬──────┘   └───────────┘ │
│                           │                          │
│                     ┌─────┴──────┐                   │
│                     │  Firehose  │                   │
│                     │ (optional) │                   │
│                     └────────────┘                   │
└─────────────────────────────────────────────────────┘

Key modules

Ark::Gateway

The central orchestrator. Receives events from Socket Mode, routes them to the appropriate handler, invokes the Bedrock agent, and posts responses back to Slack.

Ark::Slack::SocketMode

Manages the WebSocket lifecycle: calls apps.connections.open to get a WSS URL, connects, handles reconnection with backoff, and acknowledges envelopes.

Ark::Slack::Client

Wraps the Slack Web API: auth.test, chat.postMessage, reactions.add, users.info, and files.uploadV2.

Ark::Slack::Mrkdwn

Converts markdown from Bedrock responses to Slack's mrkdwn format (bold, strikethrough, links, headings).

Ark::Slack::BlockKit

Detects markdown tables in responses and renders them as Slack Block Kit table blocks.

Ark::Bedrock::Agent

Builds and signs HTTP requests to the Bedrock Agent Runtime InvokeAgent API, sends them, and parses the streaming event stream response.

Ark::Bedrock::EventStream

Decodes AWS's binary event stream protocol (application/vnd.amazon.eventstream). Each frame contains headers and a payload — the decoder extracts text chunks, citations, and output files.

Ark::AWS::Signer

Wraps the awscr-signer library for SigV4 request signing.

Ark::AWS::Credentials

Resolves AWS credentials from explicit environment variables or ~/.aws/credentials profiles.

Ark::AWS::FirehosePublisher

Publishes interaction events to Kinesis Firehose as newline-delimited JSON via signed PutRecord requests.

Design decisions

No public endpoint

Socket Mode uses an outbound WebSocket connection, so Ark needs no ingress, load balancer, or public IP.

Abstract classes for testability

Key dependencies (AgentInvoker, SlackAPI, EventPublisher) are abstract classes. The Gateway accepts them via constructor injection, making all business logic testable with mocks.

Single-threaded fibers

Crystal uses cooperative fibers, not OS threads. The gateway runs the event loop in one fiber and spawns lightweight fibers for fire-and-forget operations (reactions, analytics publishing).

Direct HTTP over AWS SDK

Crystal has no official AWS SDK. Ark uses awscr-signer for SigV4 and makes direct HTTP calls to AWS APIs, which keeps dependencies minimal and the binary small.