Documentation
¶
Overview ¶
Package harnessx is the single choke-point every PR-AF reasoner uses to call the AgentField harness. It replaces the Python monkeypatch of app.harness with an explicit generic wrapper:
- schemaFor[T] resolves the JSON-schema map the harness consumes to build its OUTPUT REQUIREMENTS prompt suffix AND to validate parsed output (design §C.3). For destination types registered by RegisterSchema it returns the committed pydantic-generated schema (parity with the Python SDK); for unknown types it falls back to invopop reflection.
- Run[T] calls the harness, classifies fatal API errors, and on a schema parse-failure hands the caller a default-seeded value so it can apply its deterministic fallback (design §C.3).
Unlike the SWE-AF harness this is adapted from, PR-AF has no scout-credential store, so Run does NOT inject run-scoped credentials into the subprocess env — opts is passed through unchanged. This is the ONLY way reasoners should reach the harness: it guarantees uniform fatal-error handling across every reasoner.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RegisterSchema ¶
RegisterSchema associates a destination type with its committed pydantic schema fixture. Call it once per Run[T] destination type (see reasoners/schemas_registry.go). Registration must complete before the first Run[T] for that type; init()-time registration guarantees this because any reasoner that calls Run[T] imports the package whose init() registers T.
func RegisteredSchema ¶
RegisteredSchema returns the resolved schema for a registered type, or (nil, false) if t has no registered fixture. Exported for the drift test, which cross-checks every embedded schema against its Go struct's json tags.
func Run ¶
func Run[T any](ctx context.Context, app HarnessCaller, prompt string, opts appx.HarnessOptions) (*T, *appx.HarnessResult, error)
Run is the single generic entry point every reasoner uses to invoke the harness for structured output of type T.
Sequence (design §C.3):
- Reflect T into the JSON schema the harness consumes (cached per type).
- Call app.Harness with a fresh *T dest. PR-AF has no scout-credential store, so — unlike the SWE-AF harness this is adapted from — Run does NOT inject run-scoped credentials into opts.Env; opts is passed through as-is.
- Classify fatal (non-retryable) API errors FIRST, before the Parsed==nil fallback, so the real billing/auth message surfaces past every retry layer as a *fatal.FatalHarnessError (callers must propagate it, not swallow it).
- On Result.Parsed == nil (the harness could not parse valid JSON into T), return a default-seeded T plus the Result — NOT an error — so the caller inspects Result.IsError and applies its role-specific deterministic fallback. The seed comes from unmarshaling "{}" into T, which triggers T's UnmarshalJSON default-seeding (schemas §C.1) when present, and yields the Go zero value otherwise.
Returns (*T, *appx.HarnessResult, error). The Result is returned even alongside a non-nil error so callers can inspect diagnostics.
Types ¶
type HarnessCaller ¶
type HarnessCaller interface {
Harness(ctx context.Context, prompt string, schema map[string]any, dest any, opts appx.HarnessOptions) (*appx.HarnessResult, error)
}
HarnessCaller is the minimal method set Run needs from *agent.Agent. Declaring it as an interface (rather than depending on the concrete *agent.Agent) lets tests supply a mock harness without a live subprocess — the same seam the Python tests get by patching the router's harness. *agent.Agent satisfies it via its Harness method (sdk/go/agent/harness.go).