Saltearse al contenido
Developer Preview — APIs and language features may change before 1.0

Effect SDKs

Esta página aún no está disponible en tu idioma.

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

LanguagePackageInstall
Pythonmashin-effectspip install mashin-effects
TypeScript@mashin/effectsnpm install @mashin/effects
SwiftMashinEffectsAdd to Package.swift (see below)
Gogithub.com/mashin-live/mashin-effects-gogo get
Rustmashin-effectsAdd to Cargo.toml (see below)
Elixirmashin_effectsAdd to mix.exs (see below)

The HTTP contract

Every effect service exposes three HTTP endpoints:

EndpointMethodPurpose
/executePOSTRun the effect. Receives {"input": {...}, "context": {...}}, returns {"status": "completed", "output": {...}, "audit": {"duration_ms": N}}
/governanceGETReturn the effect’s name, version, capabilities, and input/output schema
/healthGETReturn {"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

Cargo.toml
[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

Package.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

mix.exs
def deps do
[{:mashin_effects, "~> 0.1.0"}]
end
defmodule 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"}]
}
end
end
# Standalone
MashinEffects.start(SentimentAnalyzer, port: 8080)
# Or in a supervision tree
children = [
{MashinEffects, service: SentimentAnalyzer, port: 8080}
]

Testing your effect service

All SDKs expose the same endpoints, so you can test with curl:

Terminal window
# Health check
curl http://localhost:8080/health
# Governance declaration
curl http://localhost:8080/governance
# Execute
curl -X POST http://localhost:8080/execute \
-H "Content-Type: application/json" \
-d '{"input": {"text": "This product is great"}, "context": {}}'

Or use the CLI:

Terminal window
mashin effect test http://localhost:8080

Additional 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