flyedge

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

README

Flyedge Go SDK

Govern AI agents at the edge, where model requests, tool calls, and data cross application boundaries.

Flyedge is the Go edge runtime SDK for CompFly. It connects your agent to the CompFly control plane and applies policy at runtime, before governed model requests and tool calls execute. Use it to enforce allow, warn, or deny decisions, honor remote kill switches, and produce auditable runtime telemetry.

The SDK is deliberately explicit and idiomatic Go: construct a Guard, pass it through your application, and wire it into the boundaries you want governed. Policy denials are typed errors. There is no global singleton, import-time side effect, or framework-specific monkeypatching.

How it works

                         policy checks and decisions
Your agent ──▶ Flyedge Guard ◀────────────────────────▶ CompFly control plane
                    │
                    ├── allowed model request ────────▶ model provider
                    └── allowed tool call ────────────▶ tool or service

By default, Flyedge checks policy out of band and sends allowed model requests directly to the provider. Proxy mode is available when model traffic must pass through the CompFly gateway. Tool calls remain explicit because your application owns the agent loop and the moment a tool is executed.

Install

go get github.com/compfly-ai/flyedge-go

Requires Go 1.23+.

Quick start

Register an agent in CompFly, then provide its DID and Ed25519 signing key:

export COMPFLY_AGENT_DID="did:compfly:..."
export COMPFLY_AGENT_PRIVATE_KEY_PATH="/path/to/agent-key.pem"

Wrap the HTTP transport used by your model client to govern outbound requests:

guard, err := flyedge.New(flyedge.LoadEnv())
if err != nil {
    return err
}
defer guard.Close()

hc := &http.Client{Transport: guard.WrapRoundTripper(http.DefaultTransport)}
client := anthropic.NewClient(
    anthropicopt.WithAPIKey(os.Getenv("ANTHROPIC_API_KEY")),
    anthropicopt.WithHTTPClient(hc),
)

ctx := flyedge.ContextWithSession(context.Background(), "demo-session")
resp, err := client.Messages.New(ctx, params) // a denial surfaces as a typed error

Call CheckToolCall before executing a tool and CheckToolResponse before returning its result to the model. This is what lets Flyedge stop a dangerous action instead of merely observing it.

See the complete developer guide for Anthropic, OpenAI, Gemini, langchaingo, tool-use loops, identity, telemetry, and production configuration.

Governance points

Wire in only the boundaries you need:

Stage Guards Call
pre_llm the outgoing model request guard.WrapRoundTripper(base)
tool_call a tool the model wants to run guard.CheckToolCall(...)
tool_call_response a tool's output before it re-enters context guard.CheckToolResponse(...)
post_llm the model's response text WithResponseCheck() or guard.CheckModelResponse(...)

Flyedge governs only operations routed through these integration points. Keep your application's normal authentication and authorization in place; Flyedge adds runtime policy at the model and tool boundary. A buffered model response can be blocked before delivery. Streaming output is observed when the stream completes and cannot be retracted.

Configuration

flyedge.LoadEnv() is the single place environment is read; override fields on the returned Config before calling New.

Variable Meaning
COMPFLY_API_URL gateway base URL; defaults to https://prism.p.compfly.ai
COMPFLY_AGENT_DID the agent's DID
COMPFLY_AGENT_PRIVATE_KEY_PATH Ed25519 signing key (or COMPFLY_AGENT_PRIVATE_KEY inline)
FLYEDGE_MODE enforce | warn (default) | audit | off
FLYEDGE_FAIL_MODE fail_open (default) | fail_closed — what happens when the gateway is unreachable

The posture settings are intentionally separate:

  • In warn and audit, platform warnings are advisory. In enforce, a warning blocks.
  • A platform denial or kill-switch decision blocks in every checking mode.
  • off bypasses policy checks entirely and is intended for local development.
  • Local detectors have a separate posture, supplied by CompFly or configured in process. They can add a fast local denial but cannot override one from the control plane.

The default is fail_open: if the gateway is unreachable, the action proceeds and the error is recorded. Set fail_closed when blocking is safer than continuing during an outage. A kill-switch decision always blocks and cannot be failed open.

Protection events are summarized in memory by default. Use WithCloudTelemetry to send SDK telemetry to CompFly, or use telemetry/otel to export checks to your observability stack.

Denials are values

A check returns a Decision and an error. A policy denial is a typed *DenyError, not a panic or an opaque failure. Your agent decides whether to refuse, retry, or take another path. Kill switches surface separately as *KillSwitchError.

Packages

Package Purpose
flyedge the Guard, config, stages, sessions
enforce the wire contract and enforcement client
identity DID + Ed25519 request signing
telemetry telemetry sinks and the protection report
telemetry/otel OpenTelemetry sink (separate module)
simulation simulation client and attack injection

Examples

Runnable programs in examples/, each with its own README:

  • reference-agent — a governed Claude tool-use agent, end to end against CompFly
  • agent — one governed transport wrap across the Anthropic and OpenAI SDKs
  • openai, gemini — single-provider governed model + tool calls
  • docs-quickstart — the snippets from the developer guide, compiled
  • langchaingo, otel, manual, tools — framework, telemetry and low-level wiring
  • sim-target, attack-target — Simulation Lab / red-team targets

Docs

License

Apache-2.0. See NOTICE for attribution.

Documentation

Overview

Package flyedge is a Go agent-protection SDK, wire-compatible with the prism/policy-enforcer gateway. It is deliberately explicit ("gothonic"): construct a *Guard, pass it, and route calls through Guard.Check — no import-time monkeypatching, no ambient singletons, and a policy denial is a typed value (*DenyError), not an exception or a synthesized message.

Index

Constants

View Source
const (
	StagePreLLM           = enforce.StagePreLLM
	StageToolCall         = enforce.StageToolCall
	StageToolCallResponse = enforce.StageToolCallResponse
	StagePostLLM          = enforce.StagePostLLM

	ActionAllow = enforce.ActionAllow
	ActionDeny  = enforce.ActionDeny
	ActionWarn  = enforce.ActionWarn

	// OriginType* are the valid CheckRequest.OriginType values (prism enum, snake_case).
	OriginTypeUser       = enforce.OriginTypeUser
	OriginTypeAgent      = enforce.OriginTypeAgent
	OriginTypeAutonomous = enforce.OriginTypeAutonomous
)
View Source
const DefaultAPIURL = "https://prism.p.compfly.ai"

DefaultAPIURL is the prism gateway base URL used when Config.APIURL is empty.

View Source
const DefaultLocalControlInterval = 5 * time.Minute

DefaultLocalControlInterval is the poll cadence. Config distribution changes far less often than it is polled, and the conditional GET makes an unchanged tick nearly free, so this is chosen for "a rule change reaches the fleet promptly" rather than to limit bandwidth.

View Source
const LocalControlPollPath = "/v1/flyedge/local-controls"

LocalControlPollPath is prism's distribution endpoint for the org's local-control rule set.

View Source
const LocalControlReportPath = "/v1/flyedge/local-controls/report"

LocalControlReportPath is where an agent reports the rule set it actually applied, so an operator can see convergence rather than assuming it.

View Source
const MetadataTokens = "tokens"

MetadataTokens is the CheckRequest.Metadata key the token-budget detector reads.

It lives in metadata rather than as a CheckRequest field because the request JSON is the frozen wire schema shared with prism and the other SDKs; adding a field to feed a purely local detector would be a wire change for no server-side reader.

Variables

This section is empty.

Functions

func ContextWithAgentIdentity

func ContextWithAgentIdentity(ctx context.Context, sid, urn string) context.Context

ContextWithAgentIdentity returns a context carrying the acting agent's non-human-identity attribution: sid (subject id) and/or urn (structured identity). Both empty is ignored. These ride alongside the crypto DID (set by the signer) as additional attribution.

func ContextWithDelegation

func ContextWithDelegation(ctx context.Context, token string) context.Context

ContextWithDelegation returns a context carrying a raw delegation-token JWT (agent-to-agent authority). prism verifies it and unpacks the intent/task mandate chain encoded inside the token. Empty token is ignored.

func ContextWithEndpointAgent

func ContextWithEndpointAgent(ctx context.Context, agent EndpointAgent) context.Context

ContextWithEndpointAgent attaches the exact local endpoint-agent instance observed for a check. The instance key becomes part of the signed request body when Guard.Check runs.

func ContextWithPrincipal

func ContextWithPrincipal(ctx context.Context, p Principal) context.Context

ContextWithPrincipal returns a context carrying the end-user an agent is acting on behalf of. Every governed call (Check*, the WrapRoundTripper LLM path, Connect, telemetry) made with this context attaches the OBO header, so a single served agent identity can be governed per-user at the gateway. The zero Principal is ignored.

A production deployment also passes the underlying credential (the raw OBO token) in the request body it forwards to the provider; this envelope is prism's extraction/attribution hint.

func ContextWithSession

func ContextWithSession(ctx context.Context, id string) context.Context

ContextWithSession returns a context carrying an explicit flyedge session id. The transport wrap (and any Check that reads it) uses this id for multi-turn correlation, so a proxy or a per-conversation agent can scope sessions per request instead of per client. Empty id is ignored.

func ContextWithTrace

func ContextWithTrace(ctx context.Context, traceID, spanID string) context.Context

ContextWithTrace attaches the caller's W3C trace so a Check and its telemetry nest under the caller's span. traceID must be 32 hex chars, spanID 16 hex.

Types

type Action

type Action = enforce.Action

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type AuthContext

type AuthContext = enforce.AuthContext

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type CheckRequest

type CheckRequest = enforce.CheckRequest

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type Config

type Config struct {
	// APIURL is the prism gateway base (COMPFLY_API_URL). Empty → DefaultAPIURL.
	APIURL string
	// DID is the agent's decentralized identifier (COMPFLY_AGENT_DID), e.g.
	// did:compfly:<org_short>:<fingerprint>. Required to sign requests.
	DID string
	// KeyPEMPath is the path to the Ed25519 private key PEM (COMPFLY_AGENT_PRIVATE_KEY_PATH).
	// KeyPEM is the inline PEM (COMPFLY_AGENT_PRIVATE_KEY); it takes precedence when set.
	KeyPEMPath string
	KeyPEM     []byte
	// Mode + FailMode; empty values default to ModeWarn / FailOpen in New.
	Mode     Mode
	FailMode FailMode
	// ProxyMode routes wrapped LLM traffic through prism /v1/proxy (M2). Off = check-only.
	ProxyMode bool
	// Timeout bounds each enforcement HTTP call. Zero → 30s.
	Timeout time.Duration
	// SimTelemetryURL overrides the simulation telemetry WebSocket URL the server advertises in the
	// config's `simulation` block (COMPFLY_SIM_TELEMETRY_URL). Server-authoritative by default (empty);
	// set it only as an advanced override when the gateway hands back a telemetry URL the client
	// cannot resolve, and you need to point it at a reachable address.
	SimTelemetryURL string
}

Config is the full configuration for a Guard. Zero values are sane: an empty Config yields a warn-mode, fail-open, check-only guard against the default API URL. Populate via LoadEnv or set fields directly — there are no scattered env reads elsewhere in the package.

func LoadEnv

func LoadEnv() Config

LoadEnv builds a Config from COMPFLY_*/FLYEDGE_* environment variables. This is the single, explicit place env is read — callers may then override fields before calling New.

type Content

type Content = enforce.Content

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type Decision

type Decision = enforce.Decision

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type DenyError

type DenyError struct {
	Decision Decision
}

DenyError is returned by Check when the policy decision is a denial. Callers handle it as a value — errors.As(err, &de) — instead of catching an exception or inspecting a fake message.

func AsDenyError

func AsDenyError(err error) (*DenyError, bool)

AsDenyError is a convenience for callers: returns the *DenyError if err is one.

func (*DenyError) Error

func (e *DenyError) Error() string

type EndpointAgent

type EndpointAgent = enforce.EndpointAgent

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type ExecutionContext

type ExecutionContext = enforce.ExecutionContext

Enrichment context types (opt-in fields on CheckRequest).

type FailMode

type FailMode string

FailMode decides what happens when the enforcement call itself fails (network/5xx). It is distinct from Mode: FailOpen allows the request through, FailClosed denies it.

const (
	FailOpen   FailMode = "fail_open" // default — availability over strictness
	FailClosed FailMode = "fail_closed"
)

type Guard

type Guard struct {
	// contains filtered or unexported fields
}

Guard is the protection handle. Construct once with New, pass it explicitly, Close when done.

func New

func New(cfg Config, opts ...Option) (*Guard, error)

New builds a Guard from cfg (+ options). If a key is configured it builds a Signer; otherwise the guard runs check-only/unsigned (useful for tests/offline). Returns an error on invalid config — it never silently degrades. Importing this package has no side effects; nothing starts until New.

func (*Guard) AcknowledgeSessionTaint

func (g *Guard) AcknowledgeSessionTaint(ctx context.Context, sessionID string) error

AcknowledgeSessionTaint acknowledges all taints on a session (POST /v1/sessions/{id}/taint/acknowledge), clearing the taint gate.

func (*Guard) Check

func (g *Guard) Check(ctx context.Context, req CheckRequest) (Decision, error)

Check runs a request through the policy decision point and returns the typed Decision. Behavior by Mode: ModeOff short-circuits to allow WITHOUT calling the server; otherwise the server is called and a deny/kill ALWAYS enforces (returns *DenyError / *KillSwitchError) regardless of Mode. An advisory server `warn` blocks only in ModeEnforce (returned as deny + *DenyError); in Warn/Audit it returns (Decision{Action:Warn}, nil) for the caller to record, not block. On an enforcement-call failure it honors FailMode: FailOpen → allow + nil error; FailClosed → deny + *DenyError.

func (*Guard) CheckModelResponse

func (g *Guard) CheckModelResponse(ctx context.Context, session, model, text string) (Decision, error)

CheckModelResponse gates a model completion (the post_llm stage): run it on the model's output before returning it to the user, so policy can inspect generated content.

func (*Guard) CheckToolCall

func (g *Guard) CheckToolCall(ctx context.Context, session, toolName string, args any, destDomain string) (Decision, error)

CheckToolCall gates a tool invocation (the tool_call stage): run it before executing a tool so policy can allow/deny the call (e.g. deny egress to an external destination). args is serialized as the inspected content; destDomain is the tool's target (host/service) if it has one.

func (*Guard) CheckToolResponse

func (g *Guard) CheckToolResponse(ctx context.Context, session, toolName string, result any) (Decision, error)

CheckToolResponse gates a tool's output (the tool_call_response stage): run it on the result before feeding it back to the model, so policy can inspect returned content.

func (*Guard) Close

func (g *Guard) Close() error

Close flushes and releases resources: it stops the config poller (if Connect started one) and the telemetry sink's owned goroutine. Safe to call once.

func (*Guard) Connect

func (g *Guard) Connect(ctx context.Context, info ManifestInfo) error

Connect registers the agent's manifest with the gateway (POST /v1/flyedge/connect), enabling presence tracking and manifest-seeded baselines. Explicit — call it once at startup. Requires a signed enforcer (a real Guard); a stub/offline enforcer returns an error.

On success it also starts the config heartbeat poller (an owned goroutine, stopped by Close): the ConnectResponse carries the heartbeat cadence + initial model_mode, and the poller then keeps model_mode current, honors manifest-refresh requests, and surfaces the simulation block.

func (*Guard) DID

func (g *Guard) DID() string

DID returns the agent DID this guard signs as ("" if unsigned).

func (*Guard) GovernToolResult

func (g *Guard) GovernToolResult(ctx context.Context, session, toolName, result string) (string, Decision, error)

GovernToolResult gates a tool result AND returns the content the caller should feed back to the model. It is the value-returning companion to CheckToolResponse: use it wherever the tool result flows onward, because the governed content may differ from the raw result —

  • During an active simulation in attack mode, the attack injector may MUTATE the result (tool_poison merges adversarial fields; error_inject replaces it with a crafted error). The injection is emitted as telemetry for the platform's outcome correlation.
  • The result is always run through the tool_call_response check (enforcement + telemetry). A policy denial returns a *DenyError — the caller should withhold the result from the model.

This is the seam the injector needs for injection and that a production agent needs for response redaction: one place where the response content can be transformed, not merely allowed/denied.

func (*Guard) LocalControlDetectors

func (g *Guard) LocalControlDetectors() []string

LocalControlDetectors reports the currently active local detectors, for diagnostics and for the sync channel's status report. Nil when local controls are not configured.

func (*Guard) ModelMode

func (g *Guard) ModelMode() ModelMode

ModelMode returns the agent's current routing mode (default ModelModeCheck until the first poll).

func (*Guard) RecordLLMCall

func (g *Guard) RecordLLMCall(sessionID, requestID, model, provider string, inputTokens, outputTokens int64, latencyMS float64)

RecordLLMCall emits an llm_io event — a model call's model/provider/token/latency facts — so cost/usage observability lands on the platform (prism records GenAI metrics for llm_io). Pass a streaming bool via RecordLLMCallStreamed when relevant.

func (*Guard) RecordLLMCallDetail

func (g *Guard) RecordLLMCallDetail(c LLMCall)

RecordLLMCallDetail emits an llm_io event from a full LLMCall, including cache tiers. Prefer it over RecordLLMCall for any provider that reports prompt caching: without the cache counts the platform's view of input volume is wrong by orders of magnitude, not by a rounding error.

func (*Guard) RecordLLMCallStreamed

func (g *Guard) RecordLLMCallStreamed(sessionID, requestID, model, provider string, inputTokens, outputTokens int64, latencyMS float64, streamed bool)

RecordLLMCallStreamed is RecordLLMCall with an explicit streamed flag (stream_lifecycle).

func (*Guard) RecordSessionStart

func (g *Guard) RecordSessionStart(sessionID string, data map[string]any)

RecordSessionStart / RecordSessionSummary emit agent-session lifecycle telemetry. data is an optional payload (e.g. rolled-up stats on summary).

func (*Guard) RecordSessionSummary

func (g *Guard) RecordSessionSummary(sessionID string, data map[string]any)

func (*Guard) RecordToolIO

func (g *Guard) RecordToolIO(sessionID, requestID, toolName, argsJSON, resultJSON string)

RecordToolIO emits a tool_io event (tool name + args/result). argsJSON/resultJSON are carried as the audit request/response payloads.

func (*Guard) RecordToolIODetail

func (g *Guard) RecordToolIODetail(c ToolIO)

RecordToolIODetail emits an attributed tool_io event from a full ToolIO.

func (*Guard) Report

func (g *Guard) Report() Summary

Report returns the aggregate protection summary (checks, allowed/denied/warned/errors, timings). The caller decides whether/how to surface it — nothing is printed implicitly.

func (*Guard) SessionTaint

func (g *Guard) SessionTaint(ctx context.Context, sessionID string) (*Taint, error)

SessionTaint reads the current taint state for a session. Returns (nil, nil) when the session has no taint (prism 404s an untainted session). A returned Taint with a non-zero SessionSeverity means earlier steps tripped injection/PII/etc. signals — callers can gate on it (e.g. refuse autonomous actions above a threshold).

func (*Guard) SetLocalControls

func (g *Guard) SetLocalControls(cfg localcontrol.Config) error

SetLocalControls swaps the active local-control configuration at runtime. This is what the sync channel calls when the platform publishes a new rule set.

On a bad configuration the previous engine is KEPT and the error returned: a rule set that fails to compile must not disarm the protection that was already running. Callers should log and retry on the next sync rather than treating it as fatal.

func (*Guard) SimulationActive

func (g *Guard) SimulationActive() bool

SimulationActive reports whether the last config poll saw an active simulation run.

func (*Guard) SimulationConfig

func (g *Guard) SimulationConfig() *SimulationConfig

SimulationConfig returns a copy of the last-seen simulation block, or nil if none is active.

func (*Guard) StopLocalControlSync

func (g *Guard) StopLocalControlSync()

StopLocalControlSync stops the channel. Safe to call when it was never started.

func (*Guard) SyncLocalControls

func (g *Guard) SyncLocalControls(opts ...LocalControlSyncOption) error

SyncLocalControls starts the local-controls sync channel on this Guard.

The Guard's enforcer must be a signed HTTP enforcer (the default from New with a configured key) — the poll and report are both sensor/agent-signed. Returns an error if the transport cannot sign, rather than silently running an unauthenticated, and therefore unserved, loop.

Stop it with StopLocalControlSync, or leave it to Close.

func (*Guard) WrapRoundTripper

func (g *Guard) WrapRoundTripper(base http.RoundTripper, opts ...WrapOption) http.RoundTripper

WrapRoundTripper returns an http.RoundTripper that runs a flyedge pre_llm policy check before each outbound LLM-provider request, then forwards on Allow. It is provider-agnostic: any HTTP LLM client (the Anthropic SDK, the OpenAI SDK, raw net/http) is governed by installing this one transport — no per-framework adapter required:

hc := &http.Client{Transport: guard.WrapRoundTripper(http.DefaultTransport)}
client := anthropic.NewClient(option.WithHTTPClient(hc))   // or openai.NewClient(option.WithHTTPClient(hc))

On a policy Deny the RoundTrip returns a *DenyError (wrapped by net/http in *url.Error, still reachable via errors.As), and the provider is never called. Requests to hosts without a registered extractor pass through unchecked.

type KillInfo

type KillInfo = enforce.KillInfo

KillInfo describes an active kill switch (re-exported from enforce).

type KillSwitchError

type KillSwitchError struct {
	Kills []KillInfo
}

KillSwitchError is returned when a request is blocked by an operator kill switch — distinct from a policy DenyError because a kill ALWAYS enforces, bypassing FailMode (a kill can never be fail-open'd through). Kills carries the matching kill switch(es).

func AsKillSwitchError

func AsKillSwitchError(err error) (*KillSwitchError, bool)

AsKillSwitchError reports whether err is a *KillSwitchError.

func (*KillSwitchError) Error

func (e *KillSwitchError) Error() string

type LLMCall

type LLMCall struct {
	SessionID string
	RequestID string
	Model     string
	Provider  string

	// EndpointID / InstanceKey attribute the call to the endpoint-agent instance that made it.
	// Optional — a plain agent call leaves them empty and emits exactly as before.
	EndpointID  string
	InstanceKey string

	InputTokens      int64 // uncached input, as the provider reports it
	OutputTokens     int64
	CacheReadTokens  int64 // prompt-cache hits; frequently orders of magnitude above InputTokens
	CacheWriteTokens int64 // prompt-cache creation

	LatencyMS float64
	Streamed  *bool

	// Delegation, for a call made by a subagent rather than by the agent's main loop. A subagent
	// runs inside its parent and reports the parent's SessionID, so without these its spend is
	// indistinguishable from work the parent did itself.
	//
	// AgentID names the subagent; ParentSpanID nests the call under the work that spawned it;
	// ComponentName carries the subagent's type when the host reports one. All optional — a call
	// from the main loop leaves them empty and emits exactly as before.
	AgentID       string
	ParentSpanID  string
	ComponentName string
}

LLMCall carries the facts of one model call. Token counts are the provider's own, reported as the provider reports them: InputTokens is the UNCACHED count, with cache reads/writes separate. The wire sums them into input_tokens and ships the breakdown alongside — callers never have to decide how to combine the tiers.

type LocalControlSyncOption

type LocalControlSyncOption func(*localControlSyncSettings)

LocalControlSyncOption customizes the sync channel.

func WithLocalControlApplyHook

func WithLocalControlApplyHook(fn func(cfg localcontrol.Config, err error)) LocalControlSyncOption

WithLocalControlApplyHook observes each applied (or rejected) rule set. The SDK has no logger of its own, so this is how a host surfaces "the published rules did not compile" — without it, that failure is only visible in the report the platform receives.

func WithLocalControlInterval

func WithLocalControlInterval(d time.Duration) LocalControlSyncOption

WithLocalControlInterval overrides the poll cadence.

type ManifestInfo

type ManifestInfo struct {
	Framework   string      // e.g. "langchaingo", "anthropic-sdk-go"
	Tools       []string    // tool names the agent can call
	Models      []string    // model ids the agent uses
	Skills      []SkillInfo // Anthropic Agent Skills available to the agent (frontmatter only)
	Environment string      // dev|staging|prod

	// Enterprise is an optional enterprise-identity block (provider, tenantId, roles, groups,
	// scopes, issuer, …). prism stores it on the agent (pass-through) for enterprise governance.
	Enterprise map[string]any
	// EnterpriseToken is the optional raw enterprise identity JWT (a body credential prism carries
	// through without interpreting). Set alongside Enterprise for enterprise-authenticated agents.
	EnterpriseToken string
}

ManifestInfo is what an agent declares about itself at Connect: its framework and the tools/ models/skills it uses. The platform uses this for presence + manifest-seeded behavioral baselines.

type Mode

type Mode string

Mode is the local enforcement posture. A server-side deny or kill ALWAYS enforces regardless of Mode — Mode only decides (a) whether the policy check is called at all and (b) how an advisory server `warn` is treated locally:

  • ModeOff: skip the policy check entirely (local dev) — Check returns allow, no network call.
  • ModeAudit: check + record; never block on an advisory warn (server deny/kill still enforce).
  • ModeWarn: (default) block on server deny/kill only; a warn is advisory (returned, not blocked).
  • ModeEnforce: also treat a server warn as blocking.

Mirrors FLYEDGE_MODE in the Python SDK, whose policy middleware likewise enforces server denials independently of mode. (There are no local detectors in flyedge-go yet; when they land they follow the same posture — advisory in warn/audit, blocking in enforce.)

const (
	ModeEnforce Mode = "enforce"
	ModeWarn    Mode = "warn" // default
	ModeAudit   Mode = "audit"
	ModeOff     Mode = "off"
)

type ModelMode

type ModelMode string

ModelMode is prism's resolved routing mode for an agent. The poller keeps it current; the transport wrap (later phases) consults it to decide how to route model calls.

const (
	ModelModeCheck       ModelMode = "check"       // default: call the provider directly, check via /v1/flyedge/check
	ModelModePassthrough ModelMode = "passthrough" // route through prism carrying the agent's own key
	ModelModeGateway     ModelMode = "gateway"     // send to prism; prism supplies agent-scoped credentials
)

type Operation

type Operation = enforce.Operation

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type Option

type Option func(*Guard) error

Option customizes a Guard at construction. Options make the seams explicit and testable: inject a fake Enforcer for offline tests, or a custom Signer (KMS, agent runtime) without env plumbing.

func WithCloudTelemetry

func WithCloudTelemetry(interval time.Duration) Option

WithCloudTelemetry ships protection events to the gateway (/v1/flyedge/telemetry) via a batched, owned-goroutine sink (flushed on Close), in addition to keeping Report() working locally. interval is the flush cadence (0 → 5s). Requires the default signed HTTP enforcer.

func WithEnforcer

func WithEnforcer(e enforce.Enforcer) Option

WithEnforcer injects the policy decision point — e.g. a stub in tests, or an offline/record implementation. Overrides the default HTTP enforcer.

func WithFailMode

func WithFailMode(f FailMode) Option

WithFailMode overrides Config.FailMode.

func WithHeartbeat

func WithHeartbeat(interval time.Duration) Option

WithHeartbeat overrides the config-poll interval. By default the cadence comes from the ConnectResponse (heartbeat_interval_seconds), falling back to 30s. Set a shorter interval to pick up model-mode / simulation changes faster (e.g. during local testing).

func WithLocalControlEngine

func WithLocalControlEngine(e *localcontrol.Engine) Option

WithLocalControlEngine injects an already-built engine. Useful when a caller wants to share one engine across several Guards, or to inject a stub in tests.

func WithLocalControls

func WithLocalControls(cfg localcontrol.Config) Option

WithLocalControls enables in-process evaluation with an explicit configuration.

Most deployments should let the platform supply this through the sync channel (SyncLocalControls) rather than hardcoding it, so a rule change does not require redeploying every agent. This option exists for local development and for tests.

It returns an error when a configured pattern does not compile, so a broken rule set fails at New rather than looking active and enforcing nothing.

func WithManifestRefreshHandler

func WithManifestRefreshHandler(fn func()) Option

WithManifestRefreshHandler overrides what happens when prism sets manifest_refresh_required. The default is to re-send the manifest (reconnect); provide a handler to customize (e.g. rebuild the manifest from live introspection first).

func WithMode

func WithMode(m Mode) Option

WithMode overrides Config.Mode.

func WithModeChangeHandler

func WithModeChangeHandler(fn func(old, cur ModelMode)) Option

WithModeChangeHandler registers a callback fired when the poller observes a change to the agent's model_mode (check/passthrough/gateway). Useful for logging or reacting to a mode flip.

func WithSigner

func WithSigner(s identity.Signer) Option

WithSigner injects a Signer, overriding the one New would build from Config. Pass nil explicitly to run unsigned.

func WithSimulation

func WithSimulation(enabled bool) Option

WithSimulation enables or disables the simulation client (default: enabled). When disabled, the agent will not act as a simulation / eval target even if the platform starts a run against it — the config poller still tracks the simulation block, but no telemetry is streamed and protection is never bypassed.

func WithSimulationTelemetryURL

func WithSimulationTelemetryURL(url string) Option

WithSimulationTelemetryURL overrides the telemetry WebSocket URL the gateway advertises in the simulation config. Server-authoritative by default; set this only for split-horizon local dev (agent on the host, gateway in-cluster) so the controller dials a host-reachable URL instead of the in-cluster one. Equivalent to Config.SimTelemetryURL / COMPFLY_SIM_TELEMETRY_URL.

func WithTelemetry

func WithTelemetry(t telemetry.Telemetry) Option

WithTelemetry injects the telemetry sink (e.g. Noop, a cloud batcher, or an OTel bridge), overriding the default in-memory Recorder.

type Principal

type Principal = enforce.Principal

Principal is the on-behalf-of envelope — the end-user an agent is acting for on a request. Re-exported from enforce so callers depend only on the flyedge package. See ContextWithPrincipal.

type SimulationConfig

type SimulationConfig struct {
	Active             bool            `json:"active"`
	RunID              string          `json:"run_id"`
	Middlewares        []string        `json:"middlewares"`
	TelemetryJWT       string          `json:"telemetry_jwt"`
	TelemetryURL       string          `json:"telemetry_url"`
	ProtectionDisabled bool            `json:"protection_disabled"`
	Extra              json.RawMessage `json:"extra,omitempty"`
}

SimulationConfig is prism's `simulation` block from GET /v1/flyedge/config (frozen wire — matches prism SimulationConfig). Delivered only while a run is active. The simulation controller reacts to it, and it is surfaced via Guard.SimulationConfig / SimulationActive.

type SkillInfo

type SkillInfo struct {
	Name         string   // frontmatter `name` — the identity drift recognition matches on
	Description  string   // frontmatter `description`
	AllowedTools []string // frontmatter `allowed-tools`
	Scripts      []string // filenames under <skill>/scripts/ — names only, never contents
	Source       string   // "framework" | "config" | "filesystem" — how it was discovered
	SourcePath   string   // where it was found, e.g. the materialized pack path
}

SkillInfo is one Anthropic Agent Skill the agent has available — SKILL.md frontmatter only. Skill bodies and script contents are never shipped: the platform governs which skills exist on an agent, not what they say.

This is what makes an edge-pack-distributed skill visible to the platform: the daemon materializes it on disk, the agent declares it here, and drift recognition matches it against the org's published packs (governed) or flags it for review (not from any pack).

type Stage

type Stage = enforce.Stage

Re-export the wire types so callers depend only on the flyedge package for the common surface.

type Summary

type Summary = telemetry.Summary

Summary is the aggregate protection report (see Guard.Report).

type Taint

type Taint struct {
	Version         int          `json:"version"`
	NamespaceID     string       `json:"namespace_id"`
	SessionID       string       `json:"session_id"`
	Taints          []TaintEntry `json:"taints"`
	SessionSeverity float64      `json:"session_severity"`
	TaintHash       string       `json:"taint_hash"`
	CurrentTurn     int          `json:"current_turn"`
}

Taint is prism's SessionTaintDocument: the rolled-up taint state for a session. SessionSeverity is the aggregate score; Taints holds the individual signals.

type TaintEntry

type TaintEntry struct {
	ToolCallID     string   `json:"tool_call_id,omitempty"`
	ToolName       string   `json:"tool_name,omitempty"`
	Labels         []string `json:"labels,omitempty"`
	InjectionScore *float64 `json:"injection_score,omitempty"`
	PIIScore       *float64 `json:"pii_score,omitempty"`
	Turn           int      `json:"turn"`
	Severity       float64  `json:"severity"`
	CreatedAt      string   `json:"created_at"`
}

TaintEntry is one accrued taint signal (prism TaintEntry).

type ToolIO

type ToolIO struct {
	SessionID string
	RequestID string
	ToolName  string

	// EndpointID / InstanceKey attribute the tool call to the endpoint-agent instance that made it.
	// Optional — a plain agent call leaves them empty and emits exactly as before.
	EndpointID  string
	InstanceKey string

	ArgsJSON   string
	ResultJSON string

	TraceID        string
	SpanID         string
	ParentSpanID   string
	AgentFramework string
	Data           map[string]any
}

ToolIO carries one observed tool invocation. ArgsJSON/ResultJSON are optional audit payloads; callers that only need usage attribution can leave them empty.

type WrapOption

type WrapOption func(*guardRoundTripper)

WrapOption customizes WrapRoundTripper.

func WithResponseCheck

func WithResponseCheck() WrapOption

WithResponseCheck enables a post_llm policy check on model responses (block for non-streaming, monitor for streaming). Off by default — request-side (pre_llm) checking is always on.

Directories

Path Synopsis
Package edgesync is the generic poll/report rails behind every edge sync channel — edge packs, local controls, and whatever comes after.
Package edgesync is the generic poll/report rails behind every edge sync channel — edge packs, local controls, and whatever comes after.
Package enforce is the policy decision-point client: it signs a CheckRequest and POSTs it to prism's /v1/flyedge/check, returning a typed Decision.
Package enforce is the policy decision-point client: it signs a CheckRequest and POSTs it to prism's /v1/flyedge/check, returning a typed Decision.
Package identity implements the flyedge DID + Ed25519 request-signing contract.
Package identity implements the flyedge DID + Ed25519 request-signing contract.
Package localcontrol is the in-process policy layer: detectors that decide without a network round trip, so an obviously-destructive call is stopped at the edge and an offline agent is not an ungoverned one.
Package localcontrol is the in-process policy layer: detectors that decide without a network round trip, so an obviously-destructive call is stopped at the edge and an offline agent is not an ungoverned one.
Package simulation implements the flyedge-go client for the platform's agent simulation / attack-injection layer.
Package simulation implements the flyedge-go client for the platform's agent simulation / attack-injection layer.
Package telemetry defines the flyedge protection-telemetry seam.
Package telemetry defines the flyedge protection-telemetry seam.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL