context-compiler-example-integrations 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. context_compiler_example_integrations/README.md +71 -0
  2. context_compiler_example_integrations/__init__.py +1 -0
  3. context_compiler_example_integrations/examples/__init__.py +12 -0
  4. context_compiler_example_integrations/examples/_shared/__init__.py +1 -0
  5. context_compiler_example_integrations/examples/_shared/litellm_request.py +61 -0
  6. context_compiler_example_integrations/examples/_shared/provider_mode.py +91 -0
  7. context_compiler_example_integrations/examples/checkpoint_continuation/README.md +77 -0
  8. context_compiler_example_integrations/examples/checkpoint_continuation/example.py +169 -0
  9. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/README.md +85 -0
  10. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/app.py +205 -0
  11. context_compiler_example_integrations/examples/execution_authorization/README.md +31 -0
  12. context_compiler_example_integrations/examples/execution_authorization/expense_approval/README.md +77 -0
  13. context_compiler_example_integrations/examples/execution_authorization/expense_approval/__init__.py +1 -0
  14. context_compiler_example_integrations/examples/execution_authorization/expense_approval/example.py +168 -0
  15. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/README.md +97 -0
  16. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/__init__.py +1 -0
  17. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/app.py +312 -0
  18. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/model_approval.py +98 -0
  19. context_compiler_example_integrations/examples/gateway_middleware/README.md +49 -0
  20. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/README.md +40 -0
  21. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/__init__.py +1 -0
  22. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/example.py +220 -0
  23. context_compiler_example_integrations/examples/prompt_construction/README.md +27 -0
  24. context_compiler_example_integrations/examples/prompt_construction/litellm/README.md +197 -0
  25. context_compiler_example_integrations/examples/prompt_construction/litellm/basic.py +392 -0
  26. context_compiler_example_integrations/examples/prompt_construction/litellm/confirmation_helper.py +91 -0
  27. context_compiler_example_integrations/examples/prompt_construction/litellm/with_directive_drafter.py +524 -0
  28. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/README.md +92 -0
  29. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/__init__.py +1 -0
  30. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/example.py +205 -0
  31. context_compiler_example_integrations/examples/retrieval_filtering/README.md +65 -0
  32. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/README.md +120 -0
  33. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/__init__.py +1 -0
  34. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/example.py +320 -0
  35. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/README.md +123 -0
  36. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/__init__.py +1 -0
  37. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/example.py +300 -0
  38. context_compiler_example_integrations/examples/schema_selection/README.md +41 -0
  39. context_compiler_example_integrations/examples/schema_selection/litellm_response_format/response_format.py +218 -0
  40. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/README.md +60 -0
  41. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/example.py +171 -0
  42. context_compiler_example_integrations/examples/schema_selection/refund_intake/README.md +95 -0
  43. context_compiler_example_integrations/examples/schema_selection/refund_intake/__init__.py +1 -0
  44. context_compiler_example_integrations/examples/schema_selection/refund_intake/example.py +180 -0
  45. context_compiler_example_integrations/examples/tool_gating/README.md +55 -0
  46. context_compiler_example_integrations/examples/tool_gating/calendar_admin/README.md +34 -0
  47. context_compiler_example_integrations/examples/tool_gating/calendar_admin/__init__.py +1 -0
  48. context_compiler_example_integrations/examples/tool_gating/calendar_admin/example.py +195 -0
  49. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/README.md +93 -0
  50. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/__init__.py +1 -0
  51. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/example.py +250 -0
  52. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/live_model.py +369 -0
  53. context_compiler_example_integrations/reference_integrations/__init__.py +12 -0
  54. context_compiler_example_integrations/reference_integrations/litellm_proxy/README.md +251 -0
  55. context_compiler_example_integrations/reference_integrations/litellm_proxy/_checkpoint_support.py +146 -0
  56. context_compiler_example_integrations/reference_integrations/litellm_proxy/config.example.yaml +23 -0
  57. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook.py +163 -0
  58. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook_with_directive_drafter.py +289 -0
  59. context_compiler_example_integrations/reference_integrations/openwebui_pipe/README.md +233 -0
  60. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe.py +750 -0
  61. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe_with_directive_drafter.py +1045 -0
  62. context_compiler_example_integrations-0.1.0.dist-info/METADATA +110 -0
  63. context_compiler_example_integrations-0.1.0.dist-info/RECORD +65 -0
  64. context_compiler_example_integrations-0.1.0.dist-info/WHEEL +4 -0
  65. context_compiler_example_integrations-0.1.0.dist-info/licenses/LICENSE +173 -0
@@ -0,0 +1,71 @@
1
+ # Context Compiler Example Integrations for Python
2
+
3
+ These examples show how authoritative state changes application behavior at runtime.
4
+
5
+ Each example demonstrates a single enforcement point where premise and policy influence what a host allows, routes, retrieves, builds, or executes.
6
+
7
+ - The core authority contract is provided by [`context-compiler`](https://github.com/rlippmann/context-compiler).
8
+ - Directive recognition can optionally be added with [`context-compiler-directive-drafter`](https://github.com/rlippmann/context-compiler-directive-drafter).
9
+ - These examples focus on where authoritative state changes application behavior.
10
+
11
+ *Prompt reinjection* influences ***model behavior***.
12
+
13
+ *Context Compiler* influences ***runtime behavior***.
14
+
15
+ ## Install options
16
+
17
+ Base installation keeps this package discovery-first:
18
+
19
+ ```shell
20
+ pip install "context-compiler-example-integrations"
21
+ ```
22
+
23
+ That installs the shared core dependency only:
24
+
25
+ - `context-compiler>=0.8.0`
26
+
27
+ Add extras only for the examples you want to inspect locally:
28
+
29
+ - `pip install "context-compiler-example-integrations[drafter]"` for examples that use `context-compiler-directive-drafter`
30
+ - `pip install "context-compiler-example-integrations[retrieval]"` for ChromaDB retrieval filtering examples
31
+ - `pip install "context-compiler-example-integrations[fastapi]"` for FastAPI variants
32
+ - `pip install "context-compiler-example-integrations[litellm]"` for LiteLLM-oriented examples and reference integrations
33
+ - `pip install "context-compiler-example-integrations[all]"` to install all package-managed optional dependencies
34
+
35
+ Open WebUI is not installed by this package. The Open WebUI reference
36
+ integration assumes Open WebUI is already installed and configured as the host
37
+ runtime.
38
+
39
+ ## Generic examples
40
+
41
+ - [Checkpoint continuation](examples/checkpoint_continuation/README.md): persisted confirmation and resume flows change host behavior across turns or requests
42
+ - [Execution authorization](examples/execution_authorization/README.md): protected host actions execute only when authoritative state allows them
43
+ - [Gateway middleware](examples/gateway_middleware/README.md): the host allows, blocks, or routes requests before downstream work runs
44
+ - [Prompt construction](examples/prompt_construction/README.md): the host builds different request or prompt payloads from authoritative state
45
+ - [Retrieval filtering](examples/retrieval_filtering/README.md): the host changes which documents are eligible or relevant before returning results
46
+ - [Schema selection](examples/schema_selection/README.md): the host picks different workflow or response schemas from authoritative state
47
+ - [Tool gating](examples/tool_gating/README.md): the host changes which tools are visible or executable at runtime
48
+
49
+ ## Reference integrations
50
+
51
+ Python also includes reference integrations for runtime-specific behavior after
52
+ the generic examples.
53
+
54
+ Open a reference integration when you want to see the same kind of runtime
55
+ behavior on a specific host or framework surface.
56
+
57
+ Start with the generic example first, then use the Python reference
58
+ integrations to inspect a runtime-specific path:
59
+
60
+ - [python/reference_integrations/litellm_proxy/README.md](reference_integrations/litellm_proxy/README.md)
61
+ - [python/reference_integrations/openwebui_pipe/README.md](reference_integrations/openwebui_pipe/README.md)
62
+
63
+ ## Run an example
64
+
65
+ To explore or run an example, use a repository checkout:
66
+
67
+ 1. Clone
68
+ [`context-compiler-example-integrations`](https://github.com/rlippmann/context-compiler-example-integrations).
69
+ 2. Choose a generic example or a reference integration.
70
+ 3. Open that example's README.
71
+ 4. Follow the example-specific setup, runtime, and validation instructions.
@@ -0,0 +1 @@
1
+ """Package root for installed example integrations."""
@@ -0,0 +1,12 @@
1
+ """Example modules for installed and editable package use."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ _PACKAGE_DIR = Path(__file__).resolve().parent
8
+ _SOURCE_DIR = _PACKAGE_DIR.parents[1] / "python" / "examples"
9
+
10
+ __path__ = [str(_PACKAGE_DIR)]
11
+ if _SOURCE_DIR.is_dir():
12
+ __path__.append(str(_SOURCE_DIR))
@@ -0,0 +1 @@
1
+ """Shared helpers for Python examples."""
@@ -0,0 +1,61 @@
1
+ """Tiny shared helper for LiteLLM live-validation request kwargs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Literal, TypedDict
6
+
7
+
8
+ class ProviderConfigLike(TypedDict):
9
+ mode: Literal["openai", "ollama", "openai_compatible"]
10
+ source: str
11
+ base_url: str
12
+ model: str
13
+ api_key: str | None
14
+
15
+
16
+ class LiteLLMProviderKwargs(TypedDict, total=False):
17
+ model: str
18
+ api_base: str
19
+ api_key: str
20
+ temperature: float
21
+ drop_params: bool
22
+
23
+
24
+ def build_litellm_provider_kwargs(
25
+ config: ProviderConfigLike,
26
+ ) -> LiteLLMProviderKwargs:
27
+ """Return LiteLLM-safe provider/model kwargs for live validations."""
28
+
29
+ model = _normalize_litellm_model_id(config)
30
+ base_url = _config_value(config, "base_url")
31
+ if base_url is None:
32
+ raise RuntimeError("Provider config missing base_url.")
33
+
34
+ kwargs: LiteLLMProviderKwargs = {
35
+ "model": model,
36
+ "api_base": base_url,
37
+ "drop_params": True,
38
+ }
39
+ api_key = _config_value(config, "api_key")
40
+ if api_key:
41
+ kwargs["api_key"] = api_key
42
+ kwargs["temperature"] = 0
43
+ return kwargs
44
+
45
+
46
+ def _normalize_litellm_model_id(config: ProviderConfigLike) -> str:
47
+ mode = _config_value(config, "mode")
48
+ model = _config_value(config, "model")
49
+ if model is None:
50
+ raise RuntimeError("Provider config missing model.")
51
+ if mode == "ollama" and "/" not in model:
52
+ return f"ollama/{model}"
53
+ return model
54
+
55
+
56
+ def _config_value(config: object, key: str) -> str | None:
57
+ if isinstance(config, dict):
58
+ value = config.get(key)
59
+ else:
60
+ value = getattr(config, key, None)
61
+ return value if isinstance(value, str) or value is None else str(value)
@@ -0,0 +1,91 @@
1
+ """Shared provider mode resolution for installed example modules."""
2
+
3
+ import logging
4
+ import os
5
+ from dataclasses import dataclass
6
+ from typing import Literal, cast
7
+
8
+ _ALLOWED_PROVIDER_VALUES = ("openai", "ollama", "openai_compatible")
9
+ _STARTUP_LOGGED = False
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class ProviderConfig:
14
+ mode: Literal["openai", "ollama", "openai_compatible"]
15
+ source: Literal["default", "PROVIDER", "OPENAI_BASE_URL override"]
16
+ base_url: str
17
+ model: str
18
+ api_key: str | None
19
+
20
+
21
+ def resolve_provider_config(
22
+ default_model: str = "openai/gpt-4o-mini",
23
+ ) -> ProviderConfig:
24
+ """Resolve provider mode config from environment using strict contract."""
25
+ base_url = os.getenv("OPENAI_BASE_URL", "").strip() or None
26
+ provider = os.getenv("PROVIDER", "").strip().lower() or None
27
+ api_key = os.getenv("OPENAI_API_KEY", "").strip() or None
28
+ model = os.getenv("MODEL", "").strip() or default_model
29
+
30
+ if base_url:
31
+ return ProviderConfig(
32
+ mode="openai_compatible",
33
+ source="OPENAI_BASE_URL override",
34
+ base_url=base_url,
35
+ model=model,
36
+ api_key=api_key,
37
+ )
38
+
39
+ if provider is not None and provider not in _ALLOWED_PROVIDER_VALUES:
40
+ allowed_values = ", ".join(_ALLOWED_PROVIDER_VALUES)
41
+ raise RuntimeError(
42
+ f"Invalid PROVIDER value '{provider}'. Allowed values: {allowed_values}"
43
+ )
44
+
45
+ mode: Literal["openai", "ollama", "openai_compatible"]
46
+ source: Literal["default", "PROVIDER", "OPENAI_BASE_URL override"]
47
+ if provider is None:
48
+ mode = "openai"
49
+ source = "default"
50
+ else:
51
+ mode = cast(Literal["openai", "ollama", "openai_compatible"], provider)
52
+ source = "PROVIDER"
53
+
54
+ if mode == "openai":
55
+ if not api_key:
56
+ raise RuntimeError("OPENAI_API_KEY is required in openai mode.")
57
+ return ProviderConfig(
58
+ mode=mode,
59
+ source=source,
60
+ base_url="https://api.openai.com/v1",
61
+ model=model,
62
+ api_key=api_key,
63
+ )
64
+ if mode == "ollama":
65
+ return ProviderConfig(
66
+ mode=mode,
67
+ source=source,
68
+ base_url="http://localhost:11434",
69
+ model=model,
70
+ api_key=api_key,
71
+ )
72
+
73
+ raise RuntimeError("OPENAI_BASE_URL is required when PROVIDER=openai_compatible.")
74
+
75
+
76
+ def print_startup_config(
77
+ config: ProviderConfig, logger: logging.Logger | None = None
78
+ ) -> None:
79
+ """Emit one startup line per process with resolved provider config."""
80
+ global _STARTUP_LOGGED
81
+ if _STARTUP_LOGGED:
82
+ return
83
+ target_logger = logger or logging.getLogger(__name__)
84
+ target_logger.info(
85
+ "litellm_config mode=%s base_url=%s model=%s source=%s",
86
+ config.mode,
87
+ config.base_url,
88
+ config.model,
89
+ config.source,
90
+ )
91
+ _STARTUP_LOGGED = True
@@ -0,0 +1,77 @@
1
+ # Checkpoint continuation
2
+
3
+ Restoring a saved checkpoint changes whether a fresh host process can resume
4
+ and apply a pending itinerary change. This example shows checkpoint
5
+ continuation in a generic Python travel-booking flow.
6
+
7
+ ## Domain
8
+
9
+ The domain is a small travel-booking change flow.
10
+
11
+ The user requests a change from the current itinerary to a new itinerary.
12
+ That change requires confirmation before the host applies it.
13
+
14
+ ## Runtime
15
+
16
+ This is a generic Python example.
17
+
18
+ It does not call an LLM.
19
+
20
+ It does not use directive drafter.
21
+
22
+ ## What Context Compiler owns
23
+
24
+ Context Compiler owns:
25
+
26
+ - authoritative policy state
27
+ - the pending confirmation continuation state
28
+ - the checkpoint that captures both
29
+
30
+ In this example, the pending checkpoint state is what makes the resumed
31
+ confirmation meaningful.
32
+
33
+ Restoring authoritative state alone is not enough to resume the pending change.
34
+
35
+ ## What the host owns
36
+
37
+ The host owns:
38
+
39
+ - the booking record
40
+ - checkpoint persistence
41
+ - request/process boundaries
42
+ - the runtime behavior that actually applies the itinerary change
43
+
44
+ The host reads authoritative Context Compiler state after confirmation and
45
+ decides whether to apply the booking change.
46
+
47
+ ## Why this is not prompt reinjection
48
+
49
+ This example does not re-send hidden instructions to a model.
50
+
51
+ The observable behavior change is host-side: the booking record changes only
52
+ after a restored engine resumes the pending confirmation and authoritative
53
+ state changes.
54
+
55
+ ## Example behavior
56
+
57
+ 1. The host starts with a booking on `boston_trip`.
58
+ 2. The user initiates a switch to `chicago_trip`.
59
+ 3. Context Compiler enters a pending confirmation state.
60
+ 4. The host exports and persists the checkpoint.
61
+ 5. A fresh host process restores that checkpoint into a new engine.
62
+ 6. If the user confirms, the host applies the itinerary change.
63
+ 7. If the user rejects or sends unrelated text, the booking remains unchanged.
64
+
65
+ ## Run
66
+
67
+ From the repository root:
68
+
69
+ ```bash
70
+ uv run python python/examples/checkpoint_continuation/example.py
71
+ uv run pytest python/tests/test_checkpoint_continuation_example.py
72
+ ```
73
+
74
+ ## FastAPI variant
75
+
76
+ For a request-boundary example, see
77
+ [python/examples/checkpoint_continuation/fastapi/README.md](fastapi/README.md).
@@ -0,0 +1,169 @@
1
+ """Minimal checkpoint-continuation example for a travel booking change."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Literal, TypedDict, cast
5
+
6
+ from context_compiler import POLICY_USE, State, create_engine, get_policy_items
7
+ from context_compiler.engine import Checkpoint, Engine, State as EngineState
8
+
9
+
10
+ class BookingRecord(TypedDict):
11
+ booking_id: str
12
+ active_itinerary: str
13
+
14
+
15
+ class BookingChangeRuntimeResult(TypedDict):
16
+ compiler_input: str
17
+ decision_kind: Literal["clarify", "update", "passthrough"]
18
+ prompt_to_user: str | None
19
+ checkpoint_pending: bool
20
+ active_itinerary: str
21
+ host_applied_change: bool
22
+
23
+
24
+ @dataclass
25
+ class CheckpointStore:
26
+ """Host-owned persistence for serialized engine checkpoints."""
27
+
28
+ saved_checkpoint: Checkpoint | None = None
29
+
30
+ def save(self, checkpoint: Checkpoint) -> None:
31
+ self.saved_checkpoint = checkpoint
32
+
33
+ def load(self) -> Checkpoint:
34
+ if self.saved_checkpoint is None:
35
+ raise ValueError("no checkpoint saved")
36
+ return self.saved_checkpoint
37
+
38
+
39
+ @dataclass
40
+ class BookingHost:
41
+ """Host-owned runtime behavior for the booking example."""
42
+
43
+ booking: BookingRecord
44
+ applied_changes: list[str] = field(default_factory=list)
45
+
46
+ def apply_selected_itinerary(self, state: State) -> bool:
47
+ selected_itinerary = select_itinerary_from_state(state)
48
+ if selected_itinerary is None:
49
+ return False
50
+
51
+ self.booking["active_itinerary"] = selected_itinerary
52
+ self.applied_changes.append(selected_itinerary)
53
+ return True
54
+
55
+
56
+ def select_itinerary_from_state(state: State) -> str | None:
57
+ """Select the host-visible itinerary from authoritative state."""
58
+
59
+ use_items = list(get_policy_items(state, POLICY_USE))
60
+ if not use_items:
61
+ return None
62
+ return use_items[0]
63
+
64
+
65
+ def _decision_kind_name(
66
+ decision: object,
67
+ ) -> Literal["clarify", "update", "passthrough"]:
68
+ if not isinstance(decision, dict):
69
+ raise ValueError("unexpected decision shape")
70
+
71
+ kind = decision.get("kind")
72
+ kind_name = getattr(kind, "value", None)
73
+ if kind_name not in {"clarify", "update", "passthrough"}:
74
+ raise ValueError(f"unexpected decision kind: {kind_name}")
75
+ return cast(Literal["clarify", "update", "passthrough"], kind_name)
76
+
77
+
78
+ def initiate_itinerary_change(
79
+ engine: Engine,
80
+ *,
81
+ current_itinerary: str,
82
+ requested_itinerary: str,
83
+ ) -> BookingChangeRuntimeResult:
84
+ """Ask Context Compiler to hold a travel change behind confirmation."""
85
+
86
+ compiler_input = f"use {requested_itinerary} instead of {current_itinerary}"
87
+ decision = engine.step(compiler_input)
88
+
89
+ return {
90
+ "compiler_input": compiler_input,
91
+ "decision_kind": _decision_kind_name(decision),
92
+ "prompt_to_user": decision.get("prompt_to_user"),
93
+ "checkpoint_pending": engine.has_pending_clarification(),
94
+ "active_itinerary": select_itinerary_from_state(engine.state)
95
+ or current_itinerary,
96
+ "host_applied_change": False,
97
+ }
98
+
99
+
100
+ def restore_engine_from_checkpoint(checkpoint: Checkpoint) -> Engine:
101
+ """Restore both authoritative state and pending continuation state."""
102
+
103
+ engine = create_engine()
104
+ engine.import_checkpoint(checkpoint)
105
+ return engine
106
+
107
+
108
+ def restore_engine_from_authoritative_state_only(
109
+ checkpoint: Checkpoint,
110
+ ) -> Engine:
111
+ """Restore only authoritative state, without pending continuation state."""
112
+
113
+ authoritative_state = cast(EngineState, checkpoint["authoritative_state"])
114
+ return create_engine(state=authoritative_state)
115
+
116
+
117
+ def continue_itinerary_change(
118
+ engine: Engine,
119
+ host: BookingHost,
120
+ user_input: str,
121
+ ) -> BookingChangeRuntimeResult:
122
+ """Resume a pending change and apply host behavior only after confirmation."""
123
+
124
+ decision = engine.step(user_input)
125
+ host_applied_change = False
126
+ if _decision_kind_name(decision) == "update":
127
+ host_applied_change = host.apply_selected_itinerary(engine.state)
128
+
129
+ return {
130
+ "compiler_input": user_input,
131
+ "decision_kind": _decision_kind_name(decision),
132
+ "prompt_to_user": decision.get("prompt_to_user"),
133
+ "checkpoint_pending": engine.has_pending_clarification(),
134
+ "active_itinerary": host.booking["active_itinerary"],
135
+ "host_applied_change": host_applied_change,
136
+ }
137
+
138
+
139
+ def run_demo() -> dict[str, BookingChangeRuntimeResult | Checkpoint]:
140
+ """Run a deterministic checkpoint-continuation demonstration."""
141
+
142
+ initial_booking: BookingRecord = {
143
+ "booking_id": "booking-100",
144
+ "active_itinerary": "boston_trip",
145
+ }
146
+ first_host = BookingHost(booking=initial_booking.copy())
147
+ first_engine = create_engine()
148
+ checkpoint_store = CheckpointStore()
149
+
150
+ pending_result = initiate_itinerary_change(
151
+ first_engine,
152
+ current_itinerary=first_host.booking["active_itinerary"],
153
+ requested_itinerary="chicago_trip",
154
+ )
155
+ checkpoint_store.save(first_engine.export_checkpoint())
156
+
157
+ resumed_engine = restore_engine_from_checkpoint(checkpoint_store.load())
158
+ resumed_host = BookingHost(booking=first_host.booking.copy())
159
+ confirmed_result = continue_itinerary_change(resumed_engine, resumed_host, "yes")
160
+
161
+ return {
162
+ "pending_result": pending_result,
163
+ "confirmed_result": confirmed_result,
164
+ "saved_checkpoint": checkpoint_store.load(),
165
+ }
166
+
167
+
168
+ if __name__ == "__main__":
169
+ print(run_demo())
@@ -0,0 +1,85 @@
1
+ # Checkpoint continuation with FastAPI
2
+
3
+ A saved checkpoint lets later HTTP requests resume or reject a pending
4
+ itinerary change instead of starting over. This example shows checkpoint
5
+ continuation across stateless HTTP request boundaries.
6
+
7
+ ## Enforcement point
8
+
9
+ Checkpoint continuation
10
+
11
+ ## Domain
12
+
13
+ The domain is a small travel-booking change flow.
14
+
15
+ The first request initiates a change from `boston_trip` to `chicago_trip`.
16
+
17
+ That change requires confirmation before the host applies it.
18
+
19
+ ## Runtime
20
+
21
+ This is a small FastAPI example.
22
+
23
+ FastAPI is secondary to the enforcement point.
24
+
25
+ It exists to show that the host can persist a checkpoint between separate HTTP
26
+ requests and restore it later into a fresh engine.
27
+
28
+ ## Ownership boundary
29
+
30
+ Context Compiler owns:
31
+
32
+ - authoritative policy state
33
+ - pending continuation state
34
+ - checkpoint export and import
35
+
36
+ The host owns:
37
+
38
+ - checkpoint storage
39
+ - request routing
40
+ - booking mutation
41
+
42
+ In this example, the host creates a fresh engine per request.
43
+
44
+ The second request resumes the flow only because the host restores the saved
45
+ checkpoint, not because the process remembered a conversation.
46
+
47
+ ## Why checkpoint continuation differs from state restore
48
+
49
+ Checkpoint continuation includes pending confirmation state.
50
+
51
+ Authoritative-state-only restore does not.
52
+
53
+ That difference matters here:
54
+
55
+ - restoring the full checkpoint lets a later `yes` resume the pending trip
56
+ change
57
+ - restoring authoritative state alone does not resume that pending confirmation
58
+
59
+ ## Why this is not prompt reinjection
60
+
61
+ This example does not re-send hidden instructions to a model.
62
+
63
+ The observable behavior change is host-side: the booking only changes after a
64
+ later request restores the checkpoint and confirmation succeeds.
65
+
66
+ ## Endpoints
67
+
68
+ - `POST /change-trip`
69
+ - creates a pending confirmation
70
+ - persists a checkpoint in the host store
71
+ - `POST /confirm`
72
+ - restores the saved checkpoint into a fresh engine
73
+ - accepts `yes`, `no`, or unrelated text
74
+ - applies the booking change only after successful confirmation
75
+ - `GET /booking`
76
+ - returns the host-owned booking state
77
+
78
+ ## Validate
79
+
80
+ From the repository root:
81
+
82
+ ```bash
83
+ uv run pytest python/tests/test_fastapi_checkpoint_continuation_example.py
84
+ ./scripts/validate_python.sh
85
+ ```