rossum-agent 1.0.0rc4__tar.gz → 1.0.0rc5__tar.gz

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 (83) hide show
  1. {rossum_agent-1.0.0rc4/rossum_agent.egg-info → rossum_agent-1.0.0rc5}/PKG-INFO +6 -1
  2. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/README.md +5 -0
  3. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/pyproject.toml +1 -1
  4. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/__init__.py +1 -1
  5. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/core.py +0 -31
  6. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/models/schemas.py +4 -0
  7. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/routes/messages.py +5 -0
  8. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/prompts/base_prompt.py +1 -1
  9. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5/rossum_agent.egg-info}/PKG-INFO +6 -1
  10. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent.egg-info/SOURCES.txt +0 -1
  11. rossum_agent-1.0.0rc4/rossum_agent/agent/request_classifier.py +0 -152
  12. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/LICENSE +0 -0
  13. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/__init__.py +0 -0
  14. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/memory.py +0 -0
  15. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/models.py +0 -0
  16. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/skills.py +0 -0
  17. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent/types.py +0 -0
  18. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/agent_logging.py +0 -0
  19. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/__init__.py +0 -0
  20. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/cli.py +0 -0
  21. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/dependencies.py +0 -0
  22. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/main.py +0 -0
  23. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/models/__init__.py +0 -0
  24. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/routes/__init__.py +0 -0
  25. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/routes/chats.py +0 -0
  26. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/routes/files.py +0 -0
  27. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/routes/health.py +0 -0
  28. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/services/__init__.py +0 -0
  29. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/services/agent_service.py +0 -0
  30. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/services/chat_service.py +0 -0
  31. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/api/services/file_service.py +0 -0
  32. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/assets/Primary_light_logo.png +0 -0
  33. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/bedrock_client.py +0 -0
  34. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/prompts/__init__.py +0 -0
  35. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/prompts/system_prompt.py +0 -0
  36. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/py.typed +0 -0
  37. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/redis_storage.py +0 -0
  38. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/rossum_mcp_integration.py +0 -0
  39. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/hook-debugging.md +0 -0
  40. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/organization-setup.md +0 -0
  41. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/rossum-deployment.md +0 -0
  42. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/schema-patching.md +0 -0
  43. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/schema-pruning.md +0 -0
  44. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/skills/ui-settings.md +0 -0
  45. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/__init__.py +0 -0
  46. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/app.py +0 -0
  47. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/beep_sound.py +0 -0
  48. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/cli.py +0 -0
  49. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/render_modules.py +0 -0
  50. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/streamlit_app/response_formatting.py +0 -0
  51. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/__init__.py +0 -0
  52. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/core.py +0 -0
  53. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/deploy.py +0 -0
  54. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/dynamic_tools.py +0 -0
  55. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/file_tools.py +0 -0
  56. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/formula.py +0 -0
  57. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/skills.py +0 -0
  58. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/spawn_mcp.py +0 -0
  59. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/__init__.py +0 -0
  60. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/base.py +0 -0
  61. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/hook_debug.py +0 -0
  62. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/knowledge_base.py +0 -0
  63. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/mcp_helpers.py +0 -0
  64. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/tools/subagents/schema_patching.py +0 -0
  65. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/url_context.py +0 -0
  66. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/user_detection.py +0 -0
  67. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent/utils.py +0 -0
  68. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent.egg-info/dependency_links.txt +0 -0
  69. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent.egg-info/entry_points.txt +0 -0
  70. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent.egg-info/requires.txt +0 -0
  71. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/rossum_agent.egg-info/top_level.txt +0 -0
  72. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/setup.cfg +0 -0
  73. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_agent_logging.py +0 -0
  74. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_app_llm_response_formatting.py +0 -0
  75. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_bedrock_client.py +0 -0
  76. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_beep_sound.py +0 -0
  77. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_dynamic_tools.py +0 -0
  78. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_redis_storage.py +0 -0
  79. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_rossum_mcp_integration.py +0 -0
  80. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_smoke.py +0 -0
  81. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_url_context.py +0 -0
  82. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_user_detection.py +0 -0
  83. {rossum_agent-1.0.0rc4 → rossum_agent-1.0.0rc5}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rossum-agent
3
- Version: 1.0.0rc4
3
+ Version: 1.0.0rc5
4
4
  Summary: AI agent toolkit for Rossum: document workflows conversationally, debug pipelines automatically, and enable agentic configuration of intelligent document processing.
5
5
  Author-email: "Dan Stancl (Rossum AI)" <daniel.stancl@gmail.com>
6
6
  License: MIT
@@ -161,6 +161,7 @@ uv sync --extra streamlit # Streamlit UI only
161
161
  | `AWS_DEFAULT_REGION` | No | AWS region (default: `us-east-1`) |
162
162
  | `REDIS_HOST` | No | Redis host for chat persistence |
163
163
  | `REDIS_PORT` | No | Redis port (default: `6379`) |
164
+ | `ROSSUM_MCP_MODE` | No | MCP mode: `read-only` (default) or `read-write` |
164
165
 
165
166
  ## Usage
166
167
 
@@ -298,6 +299,10 @@ flowchart TB
298
299
 
299
300
  API docs: `/api/docs` (Swagger) or `/api/redoc`
300
301
 
302
+ **MCP Mode:** Chat sessions support mode switching via the `mcp_mode` parameter:
303
+ - Set at chat creation: `POST /api/v1/chats` with `{"mcp_mode": "read-write"}`
304
+ - Override per message: `POST /api/v1/chats/{id}/messages` with `{"content": "...", "mcp_mode": "read-write"}`
305
+
301
306
  </details>
302
307
 
303
308
  ## License
@@ -80,6 +80,7 @@ uv sync --extra streamlit # Streamlit UI only
80
80
  | `AWS_DEFAULT_REGION` | No | AWS region (default: `us-east-1`) |
81
81
  | `REDIS_HOST` | No | Redis host for chat persistence |
82
82
  | `REDIS_PORT` | No | Redis port (default: `6379`) |
83
+ | `ROSSUM_MCP_MODE` | No | MCP mode: `read-only` (default) or `read-write` |
83
84
 
84
85
  ## Usage
85
86
 
@@ -217,6 +218,10 @@ flowchart TB
217
218
 
218
219
  API docs: `/api/docs` (Swagger) or `/api/redoc`
219
220
 
221
+ **MCP Mode:** Chat sessions support mode switching via the `mcp_mode` parameter:
222
+ - Set at chat creation: `POST /api/v1/chats` with `{"mcp_mode": "read-write"}`
223
+ - Override per message: `POST /api/v1/chats/{id}/messages` with `{"content": "...", "mcp_mode": "read-write"}`
224
+
220
225
  </details>
221
226
 
222
227
  ## License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rossum-agent"
7
- version = "1.0.0rc4"
7
+ version = "1.0.0rc5"
8
8
  description = "AI agent toolkit for Rossum: document workflows conversationally, debug pipelines automatically, and enable agentic configuration of intelligent document processing."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -4,6 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  from rossum_agent.agent import AgentConfig, AgentStep, RossumAgent, create_agent
6
6
 
7
- __version__ = "1.0.0rc4"
7
+ __version__ = "1.0.0rc5"
8
8
 
9
9
  __all__ = ["AgentConfig", "AgentStep", "RossumAgent", "create_agent"]
@@ -75,7 +75,6 @@ from rossum_agent.agent.models import (
75
75
  ToolResult,
76
76
  truncate_content,
77
77
  )
78
- from rossum_agent.agent.request_classifier import RequestScope, classify_request, generate_rejection_response
79
78
  from rossum_agent.api.models.schemas import TokenUsageBreakdown
80
79
  from rossum_agent.bedrock_client import create_bedrock_client, get_model_id
81
80
  from rossum_agent.rossum_mcp_integration import MCPConnection, mcp_tools_to_anthropic_format
@@ -769,32 +768,6 @@ class RossumAgent:
769
768
  text_parts.append(text)
770
769
  return " ".join(text_parts)
771
770
 
772
- def _check_request_scope(self, prompt: UserContent) -> AgentStep | None:
773
- """Check if request is in scope, return rejection step if out of scope."""
774
- text = self._extract_text_from_prompt(prompt)
775
- result = classify_request(self.client, text)
776
- self._total_input_tokens += result.input_tokens
777
- self._total_output_tokens += result.output_tokens
778
- self._main_agent_input_tokens += result.input_tokens
779
- self._main_agent_output_tokens += result.output_tokens
780
- if result.scope == RequestScope.OUT_OF_SCOPE:
781
- rejection = generate_rejection_response(self.client, text)
782
- total_input = result.input_tokens + rejection.input_tokens
783
- total_output = result.output_tokens + rejection.output_tokens
784
- self._total_input_tokens += rejection.input_tokens
785
- self._total_output_tokens += rejection.output_tokens
786
- self._main_agent_input_tokens += rejection.input_tokens
787
- self._main_agent_output_tokens += rejection.output_tokens
788
- return AgentStep(
789
- step_number=1,
790
- final_answer=rejection.response,
791
- is_final=True,
792
- input_tokens=total_input,
793
- output_tokens=total_output,
794
- step_type=StepType.FINAL_ANSWER,
795
- )
796
- return None
797
-
798
771
  def _inject_preload_info(self, prompt: UserContent, preload_result: str) -> UserContent:
799
772
  """Inject preload result info into the user prompt."""
800
773
  suffix = (
@@ -820,10 +793,6 @@ class RossumAgent:
820
793
 
821
794
  Rate limiting is handled with exponential backoff and jitter.
822
795
  """
823
- if rejection := self._check_request_scope(prompt):
824
- yield rejection
825
- return
826
-
827
796
  loop = asyncio.get_event_loop()
828
797
  mcp_mode = get_mcp_mode()
829
798
  set_mcp_connection(self.mcp_connection, loop, mcp_mode)
@@ -133,6 +133,10 @@ class MessageRequest(BaseModel):
133
133
  description="Optional list of PDF documents (max 5) to include with the message",
134
134
  )
135
135
  rossum_url: str | None = Field(default=None, description="Optional Rossum app URL for context")
136
+ mcp_mode: Literal["read-only", "read-write"] | None = Field(
137
+ default=None,
138
+ description="MCP mode to use for this message and all subsequent messages. If not specified, uses the chat's current mode.",
139
+ )
136
140
 
137
141
 
138
142
  class StepEvent(BaseModel):
@@ -157,6 +157,11 @@ async def send_message(
157
157
 
158
158
  history = chat_data.messages
159
159
  mcp_mode = chat_data.metadata.mcp_mode
160
+ # Use message-level mode if provided, otherwise use chat's mode
161
+ if message.mcp_mode is not None:
162
+ mcp_mode = message.mcp_mode
163
+ # Update chat metadata with new mode for future messages
164
+ chat_data.metadata.mcp_mode = mcp_mode
160
165
  user_prompt = message.content
161
166
  images: list[ImageContent] | None = message.images
162
167
  documents: list[DocumentContent] | None = message.documents
@@ -5,7 +5,7 @@ Optimized for Opus 4.5: Goals + constraints, not procedures.
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
- ROSSUM_EXPERT_INTRO = """You are an expert Rossum platform specialist. Help users understand, document, debug, and configure document processing workflows.
8
+ ROSSUM_EXPERT_INTRO = """You are an expert Rossum platform specialist. Help users understand, document, debug, and configure document processing workflows. Politely redirect requests unrelated to Rossum.
9
9
 
10
10
  **CRITICAL - Use `search_knowledge_base` before**:
11
11
  - Explaining ANY extension/hook behavior (except simple function hooks you can read directly)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rossum-agent
3
- Version: 1.0.0rc4
3
+ Version: 1.0.0rc5
4
4
  Summary: AI agent toolkit for Rossum: document workflows conversationally, debug pipelines automatically, and enable agentic configuration of intelligent document processing.
5
5
  Author-email: "Dan Stancl (Rossum AI)" <daniel.stancl@gmail.com>
6
6
  License: MIT
@@ -161,6 +161,7 @@ uv sync --extra streamlit # Streamlit UI only
161
161
  | `AWS_DEFAULT_REGION` | No | AWS region (default: `us-east-1`) |
162
162
  | `REDIS_HOST` | No | Redis host for chat persistence |
163
163
  | `REDIS_PORT` | No | Redis port (default: `6379`) |
164
+ | `ROSSUM_MCP_MODE` | No | MCP mode: `read-only` (default) or `read-write` |
164
165
 
165
166
  ## Usage
166
167
 
@@ -298,6 +299,10 @@ flowchart TB
298
299
 
299
300
  API docs: `/api/docs` (Swagger) or `/api/redoc`
300
301
 
302
+ **MCP Mode:** Chat sessions support mode switching via the `mcp_mode` parameter:
303
+ - Set at chat creation: `POST /api/v1/chats` with `{"mcp_mode": "read-write"}`
304
+ - Override per message: `POST /api/v1/chats/{id}/messages` with `{"content": "...", "mcp_mode": "read-write"}`
305
+
301
306
  </details>
302
307
 
303
308
  ## License
@@ -20,7 +20,6 @@ rossum_agent/agent/__init__.py
20
20
  rossum_agent/agent/core.py
21
21
  rossum_agent/agent/memory.py
22
22
  rossum_agent/agent/models.py
23
- rossum_agent/agent/request_classifier.py
24
23
  rossum_agent/agent/skills.py
25
24
  rossum_agent/agent/types.py
26
25
  rossum_agent/api/__init__.py
@@ -1,152 +0,0 @@
1
- """Lightweight request classifier for filtering out-of-scope requests.
2
-
3
- This module provides a fast pre-filter that checks if a user request is within
4
- the scope of the Rossum platform assistant before engaging the full agent.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import logging
10
- from dataclasses import dataclass
11
- from enum import Enum
12
- from typing import TYPE_CHECKING
13
-
14
- from rossum_agent.bedrock_client import get_small_model_id
15
-
16
- if TYPE_CHECKING:
17
- from anthropic import AnthropicBedrock
18
-
19
- logger = logging.getLogger(__name__)
20
-
21
- CLASSIFIER_PROMPT = """You are a scope classifier for a Rossum document processing platform assistant.
22
-
23
- The assistant can help with:
24
- - Queue, hook, schema, and extension analysis/configuration
25
- - Debugging document processing issues and errors
26
- - Investigating hook logs and extension behavior
27
- - Explaining workflows and automation
28
- - Writing analysis reports about Rossum configuration issues
29
-
30
- IN_SCOPE: Request relates to Rossum PLATFORM operations
31
- - setting up new organization
32
- - analyzing/configuring queues, hooks, schemas, extensions
33
- - debugging errors, investigating logs
34
- - explaining workflows, analysis
35
- - generating structured report of customer use-cases on the platform
36
- - generating formula fields suggestions
37
- - Also: user asks what the assistant can do, greets assistant
38
-
39
- OUT_OF_SCOPE: Request is for DATA analytics - aggregating extracted data, generating charts/plots from document data, summarizing line items/amounts across documents, creating files unrelated to Rossum debugging. Even if it mentions Rossum annotations, if the goal is data aggregation/visualization, it's OUT_OF_SCOPE.
40
-
41
- Examples:
42
- - "Investigate errors with document splitting on queue X" → IN_SCOPE (debugging)
43
- - "Aggregate line item amounts and generate a bar chart" → OUT_OF_SCOPE (data analytics)
44
- - "Create a markdown saying hello" → OUT_OF_SCOPE (generic file creation)
45
-
46
- Respond with exactly one word: IN_SCOPE or OUT_OF_SCOPE
47
-
48
- User request: {message}"""
49
-
50
- CLASSIFIER_MAX_TOKENS = 10
51
-
52
-
53
- class RequestScope(Enum):
54
- """Classification result for a user request."""
55
-
56
- IN_SCOPE = "IN_SCOPE"
57
- OUT_OF_SCOPE = "OUT_OF_SCOPE"
58
-
59
-
60
- @dataclass
61
- class ClassificationResult:
62
- """Result of request classification."""
63
-
64
- scope: RequestScope
65
- raw_response: str
66
- input_tokens: int = 0
67
- output_tokens: int = 0
68
-
69
-
70
- @dataclass
71
- class RejectionResult:
72
- """Result of rejection response generation."""
73
-
74
- response: str
75
- input_tokens: int = 0
76
- output_tokens: int = 0
77
-
78
-
79
- REJECTION_PROMPT = """You are an expert Rossum platform specialist. The user made a request that is outside your scope.
80
-
81
- I can help with:
82
- - Analyzing and debugging hooks, extensions, and workflows
83
- - Documenting queue configurations
84
- - Investigating processing errors
85
- - Configuring automation
86
-
87
- The user asked: {message}
88
-
89
- Write a brief, helpful response that:
90
- 1. Politely explains this is outside your Rossum platform expertise
91
- 2. Briefly mentions 2-3 relevant things you CAN help with from the capabilities above
92
- 3. Asks if they have any Rossum-related questions
93
-
94
- Keep it concise (3-4 sentences max). Be friendly, not robotic."""
95
-
96
- REJECTION_MAX_TOKENS = 300
97
-
98
-
99
- def generate_rejection_response(client: AnthropicBedrock, message: str) -> RejectionResult:
100
- """Generate a contextual rejection response for out-of-scope requests."""
101
- prompt = REJECTION_PROMPT.format(message=message)
102
- try:
103
- response = client.messages.create(
104
- model=get_small_model_id(), max_tokens=REJECTION_MAX_TOKENS, messages=[{"role": "user", "content": prompt}]
105
- )
106
- text = response.content[0].text.strip() if response.content else _fallback_response()
107
- return RejectionResult(
108
- response=text, input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens
109
- )
110
- except Exception as e:
111
- logger.warning(f"Rejection response generation failed: {e}")
112
- return RejectionResult(response=_fallback_response())
113
-
114
-
115
- def _fallback_response() -> str:
116
- return (
117
- "I'm an expert Rossum platform specialist focused on document processing workflows. "
118
- "Your request appears to be outside my area of expertise. "
119
- "I can help with analyzing hooks, debugging extensions, documenting queue configurations, "
120
- "and configuring automation workflows. Do you have any Rossum-related questions?"
121
- )
122
-
123
-
124
- def classify_request(client: AnthropicBedrock, message: str) -> ClassificationResult:
125
- """Classify whether a user request is within scope.
126
-
127
- Uses a fast, cheap model (Haiku) with minimal tokens to quickly determine if the request should be processed by the main agent.
128
- """
129
- prompt = CLASSIFIER_PROMPT.format(message=message)
130
-
131
- try:
132
- response = client.messages.create(
133
- model=get_small_model_id(),
134
- max_tokens=CLASSIFIER_MAX_TOKENS,
135
- messages=[{"role": "user", "content": prompt}],
136
- )
137
-
138
- raw_response = response.content[0].text.strip().upper() if response.content else ""
139
-
140
- scope = RequestScope.OUT_OF_SCOPE if "OUT_OF_SCOPE" in raw_response else RequestScope.IN_SCOPE
141
-
142
- logger.debug(f"Request classified as {scope.value}: {message[:50]}...")
143
- return ClassificationResult(
144
- scope=scope,
145
- raw_response=raw_response,
146
- input_tokens=response.usage.input_tokens,
147
- output_tokens=response.usage.output_tokens,
148
- )
149
-
150
- except Exception as e:
151
- logger.warning(f"Classification failed, defaulting to IN_SCOPE: {e}")
152
- return ClassificationResult(scope=RequestScope.IN_SCOPE, raw_response=f"error: {e}")
File without changes