Das Go-SDK (sdk/go/ledgersdk) deckt die manuelle Record-API ab. OTel-instrumentierte Go-Apps sollten stattdessen ihren bestehenden Exporter auf den OTLP-Receiver des Ledgers richten (/v1/otlp/v1/traces) — für Go gibt es keinen sprachspezifischen Span-Prozessor.
go get github.com/bf95/AI_Comp_Ledger/sdk/go/ledgersdk
package main
import (
"time"
"github.com/bf95/AI_Comp_Ledger/sdk/go/ledgersdk"
)
func main() {
l := ledgersdk.New("http://127.0.0.1:4010", ingestKey, "urn:agent:research-assistant")
l.SetTrigger(ledgersdk.Trigger{Type: "human", Subject: "person@example.com"})
provider, model := "anthropic", "claude-fable-5"
tokensIn, tokensOut := 420, 180
response := "The policy provides that…"
span := l.Record(ledgersdk.RecordInput{
ActionType: "llm_call",
Provider: &provider,
Model: &model,
StartedAt: time.Now().Add(-time.Second),
EndedAt: time.Now(),
Status: "success",
Usage: &ledgersdk.Usage{TokensIn: &tokensIn, TokensOut: &tokensOut},
Payloads: []ledgersdk.Payload{{Kind: "response", Content: &response}},
})
l.Flush()
_ = span // die Span-ID — als ParentRef eines anderen Events für Entscheidungs-Lineage übergeben
}
Record bringt die Host-Anwendung nie mit einem Panic zum Absturz — Fehler gehen stattdessen an Ledger.OnError. Die meisten Felder sind Pointer, weil ein nil-Wert "nicht gemeldet" bedeutet, was sich von einem Nullwert unterscheidet (z. B. bedeutet Usage.TokensIn == nil unbekannt, nicht null Tokens).
Setzen Sie ParentRef (und HasParentRef: true) auf einem RecordInput, um auf die Span zu verweisen, die dieses Event verursacht hat:
parent := searchSpan
l.Record(ledgersdk.RecordInput{
ActionType: "llm_call",
ParentRef: &parent,
HasParentRef: true,
// ...
})
Flush() liefert gepufferte Events aus und kann gefahrlos per Timer oder vor dem Prozessende aufgerufen werden. Die Zustellung erfolgt at-least-once — der Server dedupliziert nach Span-ID, sodass ein wiederholter Batch nach einem fehlgeschlagenen Flush nie doppelt erfasst wird.