If your extension is written in Go and you control the build, you can implement sdk.Extension (an alias of agent.Extension) directly — no gRPC, no subprocess, no socket. This is the lowest-overhead extension path.
All types are re-exported from sdk so callers only need to import github.com/goppydae/sharur/sdk.
Key Hook Behaviours
ModifyInput — runs before the user text is added to the transcript. Return an InputResult with:
sdk.InputContinue — pass through unchanged
sdk.InputTransform — replace with result.Text
sdk.InputHandled — consume entirely; no agent turn is started and nothing is appended to the transcript
ModifyContext — receives and returns the message slice that will be sent to the LLM. Changes do not affect the stored session transcript — they are ephemeral per-turn.
BeforeToolCall — return (result, true) to intercept and block the tool; return (nil, false) to allow normal execution.
BeforeCompact — return nil to let the default LLM summarization run, or a *CompactionResult to supply your own summary and skip the LLM call.
typesandboxExtstruct{sdk.NoopExtensionallowedDirstring}func(e*sandboxExt)BeforeToolCall(_context.Context,call*sdk.ToolCall,argsjson.RawMessage)(*sdk.ToolResult,bool){varinputstruct{Pathstring`json:"path"`}_=json.Unmarshal(args,&input)ifinput.Path!=""&&!strings.HasPrefix(input.Path,e.allowedDir){return&sdk.ToolResult{Content:fmt.Sprintf("blocked: %s is outside %s",input.Path,e.allowedDir),IsError:true,},true}returnnil,false}