Effect SDKs
このコンテンツはまだ日本語訳がありません。
mashin provides SDKs in six languages for building external effect services. Each SDK implements the same HTTP contract, so your effect service works the same way regardless of what language it is written in.
For a guided walkthrough of building an effect service, see Building Effect Machines.
Available SDKs
| Language | Package | Install |
|---|---|---|
| Python | mashin-effects | pip install mashin-effects |
| TypeScript | @mashin/effects | npm install @mashin/effects |
| Swift | MashinEffects | Add to Package.swift (see below) |
| Go | github.com/mashin-live/mashin-effects-go | go get |
| Rust | mashin-effects | Add to Cargo.toml (see below) |
| Elixir | mashin_effects | Add to mix.exs (see below) |
The HTTP contract
Every effect service exposes three HTTP endpoints:
| Endpoint | Method | Purpose |
|---|---|---|
/execute | POST | Run the effect. Receives {"input": {...}, "context": {...}}, returns {"status": "completed", "output": {...}, "audit": {"duration_ms": N}} |
/governance | GET | Return the effect’s name, version, capabilities, and input/output schema |
/health | GET | Return {"status": "healthy", "version": "0.1.0"} |
The SDK handles the HTTP server, routing, request parsing, error handling, and audit timing. You implement two functions: execute (your logic) and governance (your declaration).
Quick start by language
Python
from mashin_effects import EffectService
class SentimentAnalyzer(EffectService): name = "sentiment-analyzer" version = "1.0.0" capabilities = ["external_api_call"] inputs = [{"name": "text", "type": "string", "required": True}] outputs = [{"name": "sentiment", "type": "string"}, {"name": "score", "type": "number"}]
def execute(self, input, context): text = input.get("text", "") # Your analysis logic here return {"sentiment": "positive", "score": 0.85}
if __name__ == "__main__": SentimentAnalyzer().serve(port=8080)TypeScript
import { EffectService } from "@mashin/effects";
class SentimentAnalyzer extends EffectService { governance() { return { name: "sentiment-analyzer", version: "1.0.0", capabilities: ["external_api_call"], inputs: [{ name: "text", type: "string", required: true }], outputs: [{ name: "sentiment", type: "string" }, { name: "score", type: "number" }], }; }
async execute(input: Record<string, any>, context: Record<string, any>) { const text = input.text ?? ""; // Your analysis logic here return { sentiment: "positive", score: 0.85 }; }}
new SentimentAnalyzer().serve({ port: 8080 });Go
package main
import effects "github.com/mashin-live/mashin-effects-go"
type SentimentAnalyzer struct{}
func (s SentimentAnalyzer) Execute(input, context map[string]any) (map[string]any, error) { text, _ := input["text"].(string) _ = text // Your analysis logic here return map[string]any{"sentiment": "positive", "score": 0.85}, nil}
func (s SentimentAnalyzer) Governance() effects.GovernanceDeclaration { return effects.GovernanceDeclaration{ Name: "sentiment-analyzer", Version: "1.0.0", Capabilities: []string{"external_api_call"}, Inputs: []effects.FieldSpec{{Name: "text", Type: "string", Required: true}}, Outputs: []effects.FieldSpec{{Name: "sentiment", Type: "string"}, {Name: "score", Type: "number"}}, }}
func main() { effects.Serve(SentimentAnalyzer{}, effects.WithPort(8080))}Rust
[dependencies]mashin-effects = "0.1"tokio = { version = "1", features = ["full"] }async-trait = "0.1"serde_json = "1"use async_trait::async_trait;use mashin_effects::{EffectService, GovernanceDeclaration, serve};use std::collections::HashMap;use serde_json::Value;
struct SentimentAnalyzer;
#[async_trait]impl EffectService for SentimentAnalyzer { async fn execute( &self, input: HashMap<String, Value>, _context: HashMap<String, Value>, ) -> Result<HashMap<String, Value>, Box<dyn std::error::Error + Send + Sync>> { let mut output = HashMap::new(); output.insert("sentiment".into(), Value::from("positive")); output.insert("score".into(), Value::from(0.85)); Ok(output) }
fn governance(&self) -> GovernanceDeclaration { GovernanceDeclaration { name: "sentiment-analyzer".into(), version: "1.0.0".into(), capabilities: vec!["external_api_call".into()], inputs: vec![], outputs: vec![], rate_limits: None, } }}
#[tokio::main]async fn main() { serve(SentimentAnalyzer, 8080).await.unwrap();}Swift
dependencies: [ .package(url: "https://github.com/mashin-live/mashin-effects-swift.git", from: "0.1.0"),]import MashinEffects
struct SentimentAnalyzer: EffectService { func execute(input: [String: Any], context: [String: Any]) async throws -> [String: Any] { return ["sentiment": "positive", "score": 0.85] }
func governance() -> GovernanceDeclaration { GovernanceDeclaration( name: "sentiment-analyzer", version: "1.0.0", capabilities: ["external_api_call"], inputs: [FieldSpec(name: "text", type: "string", required: true)], outputs: [FieldSpec(name: "sentiment", type: "string"), FieldSpec(name: "score", type: "number")] ) }}
@main struct Main { static func main() async throws { let server = EffectServer(service: SentimentAnalyzer(), host: "0.0.0.0", port: 8080) try await server.run() }}Elixir
def deps do [{:mashin_effects, "~> 0.1.0"}]enddefmodule SentimentAnalyzer do @behaviour MashinEffects.Service
@impl true def execute(input, _context) do {:ok, %{"sentiment" => "positive", "score" => 0.85}} end
@impl true def governance do %{ "name" => "sentiment-analyzer", "version" => "1.0.0", "capabilities" => ["external_api_call"], "inputs" => [%{"name" => "text", "type" => "string", "required" => true}], "outputs" => [%{"name" => "sentiment", "type" => "string"}, %{"name" => "score", "type" => "number"}] } endend
# StandaloneMashinEffects.start(SentimentAnalyzer, port: 8080)
# Or in a supervision treechildren = [ {MashinEffects, service: SentimentAnalyzer, port: 8080}]Testing your effect service
All SDKs expose the same endpoints, so you can test with curl:
# Health checkcurl http://localhost:8080/health
# Governance declarationcurl http://localhost:8080/governance
# Executecurl -X POST http://localhost:8080/execute \ -H "Content-Type: application/json" \ -d '{"input": {"text": "This product is great"}, "context": {}}'Or use the CLI:
mashin effect test http://localhost:8080Additional language examples
Beyond the six SDKs, the sdks/examples/ directory has standalone examples in Bun, Deno, Gleam, Zig, Kotlin, Ruby, and C#. These implement the HTTP contract directly without an SDK, proving that any language can participate as a mashin effect service.
Next steps
- Building Effect Machines - Full guide to creating and registering effects
- CLI Effect Commands - Managing effect services from the terminal