Help us improve
Share bugs, ideas, or general feedback.
From trebuchet
Serverless deployment architecture with CloudGateway, CloudProvider abstraction, ServiceRegistry, ActorStateStore, and local development setup. Use when users need to understand cloud deployment concepts or deploy actors to serverless platforms.
npx claudepluginhub briannadoubt/claude-marketplace --plugin trebuchetHow this skill is triggered — by the user, by Claude, or both
Slash command
/trebuchet:skills/cloud-deploymentThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Learn how Trebuchet enables serverless deployment of distributed actors.
Converts existing projects into Apify Actors for serverless cloud execution. Supports JavaScript/TypeScript, Python, and CLI-wrapped tools. Use for migrating code to Apify or wrapping CLI tools as Actors.
Builds, deploys, manages, debugs, configures, and optimizes AWS serverless apps using Lambda, API Gateway, Step Functions, EventBridge, SAM/CDK. Covers cold starts, concurrency, CORS, event sources.
Converts existing software into Apify Actors: Docker-packaged serverless apps with JSON input/output. Guides apify init, SDK integration, schema config, local testing, and deployment.
Share bugs, ideas, or general feedback.
Learn how Trebuchet enables serverless deployment of distributed actors.
TrebuchetCloud provides the abstractions needed to deploy Swift distributed actors to serverless platforms. Instead of running a persistent server, your actors execute on-demand in response to invocations.
┌───────────────────────────────────────────────────────────────┐
│ Cloud Environment │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ CloudGateway │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │
│ │ │ UserService │ │ GameRoom │ │ Lobby │ │ │
│ │ └─────────────┘ └─────────────┘ └────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────┐ │
│ │ StateStore │ │ Registry │ │ HTTP Endpoint │ │
│ │ (DynamoDB) │ │ (CloudMap) │ │ (API Gateway) │ │
│ └──────────────┘ └──────────────┘ └───────────────────┘ │
└───────────────────────────────────────────────────────────────┘
The CloudGateway is the entry point for hosting actors in cloud environments. It handles:
import TrebuchetCloud
let gateway = CloudGateway(configuration: .init(
host: "0.0.0.0",
port: 8080,
stateStore: myStateStore,
registry: myRegistry
))
try await gateway.expose(myActor, as: "my-actor")
try await gateway.run()
The CloudProvider protocol abstracts cloud platform specifics:
public protocol CloudProvider: Sendable {
associatedtype FunctionConfig: Sendable
associatedtype DeploymentResult: CloudDeployment
func deploy<A: DistributedActor>(
_ actorType: A.Type,
as actorID: String,
config: FunctionConfig,
factory: @Sendable (TrebuchetActorSystem) -> A
) async throws -> DeploymentResult
func transport(for deployment: DeploymentResult) async throws -> any TrebuchetTransport
}
Implementations:
The ServiceRegistry protocol enables actor discovery:
public protocol ServiceRegistry: Sendable {
func register(
actorID: String,
endpoint: CloudEndpoint,
metadata: [String: String],
ttl: Duration?
) async throws
func resolve(actorID: String) async throws -> CloudEndpoint?
func deregister(actorID: String) async throws
}
Implementations:
The ActorStateStore protocol provides state persistence:
public protocol ActorStateStore: Sendable {
func load<State: Codable & Sendable>(
for actorID: String,
as type: State.Type
) async throws -> State?
func save<State: Codable & Sendable>(
_ state: State,
for actorID: String
) async throws
func delete(for actorID: String) async throws
}
Implementations:
Actors that need persistent state implement StatefulActor:
import TrebuchetCloud
@Trebuchet
distributed actor ShoppingCart: StatefulActor {
typealias PersistentState = CartState
let stateStore: ActorStateStore
var persistentState = CartState()
init(actorSystem: TrebuchetActorSystem, stateStore: ActorStateStore) async throws {
self.actorSystem = actorSystem
self.stateStore = stateStore
try await loadState(from: stateStore)
}
distributed func addItem(_ item: Item) async throws -> CartState {
persistentState.items.append(item)
try await saveState(to: stateStore)
return persistentState
}
func loadState(from store: any ActorStateStore) async throws {
if let state = try await store.load(for: id.id, as: CartState.self) {
persistentState = state
}
}
func saveState(to store: any ActorStateStore) async throws {
try await store.save(persistentState, for: id.id)
}
}
struct CartState: Codable, Sendable {
var items: [Item] = []
}
Actors deployed to cloud functions can discover and invoke each other in two ways:
import TrebuchetCloud
import TrebuchetAWS
// From within an actor running in Lambda
@Trebuchet
distributed actor GameRoom {
let client: TrebuchetCloudClient
distributed func notifyLobby() async throws {
// Resolve another actor via service registry
let lobby = try await client.resolve(Lobby.self, id: "lobby")
// Invoke it (triggers another Lambda invocation)
try await lobby.onGameStarted(roomID: id.id)
}
}
Added in v0.3.0 - For programmatic actor invocation without HTTP overhead:
import TrebuchetCloud
let gateway = CloudGateway(configuration: .init(
stateStore: stateStore,
registry: registry
))
// Register actors
try await gateway.expose(myActor, as: "my-actor")
// Programmatic invocation (actor-to-actor, no HTTP)
let envelope = InvocationEnvelope(
callID: UUID(),
actorID: TrebuchetActorID(id: "my-actor"),
targetIdentifier: "myMethod(param:)",
genericSubstitutions: [],
arguments: [try JSONEncoder().encode("value")]
)
let response = await gateway.process(envelope)
Use cases:
For local development, use the in-memory implementations:
import TrebuchetCloud
let gateway = CloudGateway.development(host: "localhost", port: 8080)
This creates a gateway with:
InMemoryStateStore for state persistenceInMemoryRegistry for service discoveryimport Trebuchet
import TrebuchetCloud
@main
struct DevServer {
static func main() async throws {
// Create local gateway
let gateway = CloudGateway.development(host: "localhost", port: 8080)
// Create actors
let room = GameRoom(actorSystem: gateway.system)
let lobby = Lobby(actorSystem: gateway.system)
// Expose actors
try await gateway.expose(room, as: "game-room")
try await gateway.expose(lobby, as: "lobby")
print("Local development server running on http://localhost:8080")
try await gateway.run()
}
}
@Trebuchet macrotrebuchet.yamltrebuchet deploy --provider awsCreate a trebuchet.yaml to configure deployment:
name: my-game-server
version: "1"
defaults:
provider: aws
region: us-east-1
memory: 512
timeout: 30
actors:
GameRoom:
memory: 1024
stateful: true
Lobby:
memory: 256
state:
type: dynamodb
discovery:
type: cloudmap
namespace: my-game
CloudGateway supports middleware for cross-cutting concerns:
import TrebuchetCloud
import TrebuchetSecurity
import TrebuchetObservability
let gateway = CloudGateway(configuration: .init(
middlewares: [
ValidationMiddleware(...), // Request validation
AuthenticationMiddleware(...), // Authentication
AuthorizationMiddleware(...), // Authorization
RateLimitingMiddleware(...), // Rate limiting
TracingMiddleware(...) // Distributed tracing
],
stateStore: stateStore,
registry: registry
))