dsh-spill-s3
S3-compatible spill backend for DeepSeek Harness: oversized tool output goes to object storage (AWS S3, MinIO, R2) instead of the agent's local disk
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:tancheng33/dsh-spill-s3说明文档
阅读完整 README ↗Configuration
| Key | Default | Meaning |
|---|---|---|
endpoint | https://s3.us-east-1.amazonaws.com | Service endpoint origin. |
region | us-east-1 | Region in the SigV4 credential scope. S3-compatible servers accept any consistent value. |
bucket | (required) | Destination bucket. It must already exist — this plugin never creates one. |
prefix | dsh-spill | Key prefix. Artifacts land under ` |
| /session-/`. | ||
forcePathStyle | true | host/bucket/key addressing. Required by MinIO and bare-IP endpoints; set false for AWS virtual-host style. |
accessKeyIdRef | AWS_ACCESS_KEY_ID | Credential reference — a name, not a value. |
secretAccessKeyRef | AWS_SECRET_ACCESS_KEY | Reference for the secret key. |
sessionTokenRef | AWS_SESSION_TOKEN | Reference for an STS session token. Ignored when unset. |
serverSideEncryption | AES256 | x-amz-server-side-encryption value. Empty sends no header. |
retrieval | cli | How the model is told to read an artifact: cli, presigned, or locator-only. |
presignExpiresSeconds | 3600 | Presigned URL lifetime (1..604800). |
timeoutMs | 30000 | Upload timeout. |
Credentials are references, not values
accessKeyIdRef names a credential; the value is resolved per upload through ctx.credentials, falling back to the process environment when no credential provider is mounted. Nothing secret belongs in cordis.patch.yml.
Because resolution is per operation (the seam's own contract), a rotated key reaches the next upload without restarting anything. Pair it with a central secret store — e.g. dsh-credentials-vault — and the agent host never holds a long-lived AWS key at all.
Choosing a retrieval mode
| Mode | The model is told | Cost |
|---|---|---|
cli (default) | run aws s3 cp s3://… | needs the AWS CLI and credentials on the machine running commands |
presigned | fetch this URL | puts a bearer URL in the model's context and the durable session log |
locator-only | ask the user | safest; the model cannot self-serve |
presigned is genuinely useful — it makes a spilled artifact readable with a plain web_fetch — but a presigned URL is a bearer credential with a lifetime. It is opt-in for that reason.