Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions src/components/react/ThemeImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { CSSProperties } from 'react';

interface ThemeImageProps {
/** Image shown in light mode. */
light: string;
/** Image shown in dark mode. */
dark: string;
alt: string;
width?: number | string;
height?: number | string;
className?: string;
style?: CSSProperties;
}

/**
* Renders a light and dark version of an image and swaps between them based on
* the active `data-theme`. The swap is pure CSS (see custom.css), so there's no
* hydration flash — both `<img>`s are in the DOM and only one is displayed.
*
* The images carry their own alpha channel (the flat canvas is keyed out to
* transparency), so the artwork floats on any surface — page body, nav, a
* callout, the dark-mode ambient texture. That's why this uses transparency
* rather than `mix-blend-mode`: a blend only melts into a flat backdrop in the
* same stacking context and leaves a seam anywhere the surface isn't that exact
* color.
*/
export function ThemeImage({
light,
dark,
alt,
width,
height,
className,
style,
}: ThemeImageProps) {
return (
<span
className={`theme-image-frame${className ? ` ${className}` : ''}`}
style={style}
>
<img
src={light}
alt={alt}
width={width}
height={height}
className="theme-image theme-image--light"
/>
<img
src={dark}
alt={alt}
width={width}
height={height}
aria-hidden="true"
className="theme-image theme-image--dark"
/>
</span>
);
}
1 change: 1 addition & 0 deletions src/components/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export { SearchDialog } from './SearchDialog';
export { SearchDialogWrapper } from './SearchDialogWrapper';
export { StatusBadge, StatusCodes } from './StatusCodes';
export { StatusIcon } from './StatusIcon';
export { ThemeImage } from './ThemeImage';
export { ThemeSwitcher } from './ThemeSwitcher';
12 changes: 9 additions & 3 deletions src/content/docs/integrations/claude-managed-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
description: Run Anthropic Claude Managed Agents with tool execution inside your own Sprites
---

import { Callout } from '@/components/react';
import SelfHostedDiagram from '@/components/SelfHostedDiagram.astro';
import { Callout, ThemeImage } from '@/components/react';
import { Tabs, TabItem } from '@astrojs/starlight/components';

<img
Expand All @@ -19,9 +18,16 @@

## How it works

A self-hosted environment is a work queue. When a session is assigned to it, Anthropic enqueues a work item. A worker you run claims the item and starts a per-session Sprite that runs Anthropic's tool runner. Tool inputs and outputs flow back to Anthropic so the model can see results; everything the tools touch stays in the Sprite.

Check warning on line 21 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'enqueues' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'enqueues' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 21, "column": 88}}}, "severity": "INFO"}

<SelfHostedDiagram />
<ThemeImage
light="/images/integrations/claude-managed-agents-light.webp"
dark="/images/integrations/claude-managed-agents-dark.webp"
alt="Lifecycle loop: the Claude Platform enqueues a work item; a worker you run claims it and launches a per-session Sprite, and tool calls round-trip between the Platform and the Sprite where everything the tools touch stays"

Check warning on line 26 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'enqueues' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'enqueues' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 26, "column": 44}}}, "severity": "INFO"}
width={1672}
height={941}
style={{ maxWidth: '42rem', marginInline: 'auto', marginBlock: '2rem' }}

Check warning on line 29 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'marginBlock' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'marginBlock' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 29, "column": 53}}}, "severity": "INFO"}

Check warning on line 29 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'marginInline' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'marginInline' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 29, "column": 31}}}, "severity": "INFO"}

Check warning on line 29 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'maxWidth' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'maxWidth' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 29, "column": 12}}}, "severity": "INFO"}
/>

The runner authenticates with an **environment key**, the only credential it needs for both the control plane and the per-session calls. Your organization API key never reaches the Sprite.

Expand Down Expand Up @@ -68,7 +74,7 @@

### Spawn a Sprite per session

The worker creates a Sprite, uploads Anthropic's provider-agnostic runner, installs the SDK, and launches it as a Sprite [service](/concepts/services) rather than a detached `nohup` process. A service is supervised: the Sprite owns it, so it survives beyond the request that created it and is restored on wake, neither of which a process backgrounded inside a single request can be counted on to do. Because a service that exits is otherwise restarted, the one-shot worker stops itself on completion so it is not brought back up.

Check warning on line 77 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'backgrounded' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'backgrounded' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 77, "column": 339}}}, "severity": "INFO"}

The `ANTHROPIC_*` variables are written to a file the service sources rather than passed as service arguments, so the environment key never appears in process listings. The service deletes the file right after sourcing it, so the key isn't left on the Sprite's disk.

Expand All @@ -90,7 +96,7 @@
# Anthropic's provider-agnostic runner. One call is the whole worker: it builds
# the per-session tool context, downloads skills, runs the tool loop, and posts
# results back. See the cookbook for the full file.
RUNNER_SRC = '''import asyncio, logging, os, sys

Check warning on line 99 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'sys' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'sys' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 99, "column": 46}}}, "severity": "INFO"}

Check warning on line 99 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'asyncio' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'asyncio' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 99, "column": 24}}}, "severity": "INFO"}
from anthropic import AsyncAnthropic

# The worker reports its lifecycle only through stdlib logging; send it to
Expand All @@ -98,9 +104,9 @@
# (/.sprite/logs/services/agent-runner.log).
logging.basicConfig(level=logging.INFO, stream=sys.stdout)

async def main():

Check warning on line 107 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'async' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'async' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 107, "column": 1}}}, "severity": "INFO"}
key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
async with AsyncAnthropic(auth_token=key) as client:

Check warning on line 109 in src/content/docs/integrations/claude-managed-agents.mdx

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'async' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'async' a typo?", "location": {"path": "src/content/docs/integrations/claude-managed-agents.mdx", "range": {"start": {"line": 109, "column": 5}}}, "severity": "INFO"}
# handle_item() services the single already-claimed item, reading
# ANTHROPIC_WORK_ID / ANTHROPIC_SESSION_ID / ANTHROPIC_ENVIRONMENT_ID /
# ANTHROPIC_ENVIRONMENT_KEY from the env (written to runner.env below).
Expand Down
23 changes: 23 additions & 0 deletions src/styles/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -2135,3 +2135,26 @@ h2.method-title {
--co-decoration-hover: #1e3a8a99;
--co-link-hover: #172554;
}

/* Theme-aware image swap (ThemeImage component)
Both variants render into the DOM; CSS shows the one matching the active
theme. The images have transparent (keyed) backgrounds, so the artwork floats
on any surface with no blend mode or matching backdrop needed. */
.theme-image-frame {
display: block;
line-height: 0;
}
.theme-image {
display: block;
width: 100%;
height: auto;
}
.theme-image--dark {
display: none;
}
[data-theme='dark'] .theme-image--light {
display: none;
}
[data-theme='dark'] .theme-image--dark {
display: block;
}
Loading