Integrations
Stripe
Trigger AgentField reasoners from signed Stripe webhooks.
The stripe source verifies the Stripe-Signature header and dispatches payment events through AgentField.
Source Surface
| Surface | Value |
|---|---|
| Source name | stripe |
| Kind | HTTP webhook |
| Secret | Required; Stripe endpoint signing secret from secret_env |
| Config | Optional tolerance_seconds, default 300 |
| Event type | Stripe event type |
| Idempotency | Stripe event id |
| Reasoner input | Normalized { id, type, data } as event, with trigger metadata in _meta |
Stripe does not ship a separate capability node in OSS. The integration surface is the signed webhook source.
Agent Code
from agentfield import Agent, on_event
app = Agent(node_id="billing-agent")
@app.reasoner()
@on_event(
source="stripe",
types=["payment_intent.succeeded", "checkout.session.completed", "invoice.paid"],
secret_env="STRIPE_WEBHOOK_SECRET",
)
async def handle_stripe(event: dict, trigger=None):
data = event.get("data", {}).get("object", {})
return {
"stripe_event": event.get("type"),
"stripe_id": data.get("id"),
"delivery": trigger.idempotency_key if trigger else event.get("id"),
}
app.run()import { Agent } from '@agentfield/sdk';
const agent = new Agent({ nodeId: 'billing-agent' });
// The stripe source verifies Stripe-Signature, then dispatches the
// normalized { id, type, data } as ctx.input.event with metadata in
// ctx.input._meta. The TypeScript SDK has no declarative source binding —
// connect the `stripe` source to this reasoner from the UI (or trigger REST API).
agent.reasoner('handleStripe', async (ctx) => {
const { event, _meta } = ctx.input;
const data = event?.data?.object ?? {};
return {
stripe_event: event?.type,
stripe_id: data.id,
delivery: _meta?.idempotency_key ?? event?.id,
};
});
agent.serve();a, _ := agent.New(agent.Config{NodeID: "billing-agent", Version: "1.0.0"})
// Declare the stripe binding in code. The control plane verifies
// Stripe-Signature with STRIPE_WEBHOOK_SECRET, then dispatches the
// normalized { id, type, data } as input["event"] with metadata in
// input["_meta"].
a.RegisterReasoner("handle_stripe", func(ctx context.Context, input map[string]any) (any, error) {
event, _ := input["event"].(map[string]any)
meta, _ := input["_meta"].(map[string]any)
data := map[string]any{}
if d, ok := event["data"].(map[string]any); ok {
if obj, ok := d["object"].(map[string]any); ok {
data = obj
}
}
var delivery any = event["id"]
if meta != nil {
delivery = meta["idempotency_key"]
}
return map[string]any{
"stripe_event": event["type"],
"stripe_id": data["id"],
"delivery": delivery,
}, nil
},
agent.WithEventTrigger("stripe", "payment_intent.succeeded", "checkout.session.completed", "invoice.paid"),
agent.WithTriggerSecretEnv("STRIPE_WEBHOOK_SECRET"),
)
a.Serve(context.Background())Stripe Setup
Create a webhook endpoint in Stripe and paste the AgentField trigger URL. Select the event types your reasoner handles and store the endpoint signing secret in the env var named by secret_env.
Common event types:
payment_intent.succeededcheckout.session.completedinvoice.paidcustomer.subscription.updated
Dispatch Contract
AgentField keeps the reasoner input small and stable:
{
"event": {
"id": "evt_123",
"type": "invoice.paid",
"data": {
"object": { "id": "in_123", "customer": "cus_123" }
}
},
"_meta": {
"source": "stripe",
"event_type": "invoice.paid",
"idempotency_key": "evt_123"
}
}- The Stripe event
idbecomes the idempotency key. - Signature timestamps are checked against a tolerance window.
- The raw payload is stored for audit; the normalized event is dispatched to the reasoner.