Skip to content

Conversation

@groupthinking
Copy link
Owner

This pull request makes minor updates to the README.md to clarify the project description and simplify the instructions for obtaining an xAI / Grok API key.

  • Updated project description to clarify that the agent acts based on thread context and reasoning, rather than just detecting mentions and routing reasoning.
  • Simplified the xAI / Grok API key instructions by removing the requirement for an X Premium+ subscription and streamlining the steps.

Removed redundant text from the introduction section.
Removed duplicate steps for creating and storing the xAI / Grok API key.
@groupthinking groupthinking marked this pull request as ready for review January 28, 2026 16:55
Copilot AI review requested due to automatic review settings January 28, 2026 16:55
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @groupthinking, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the clarity and accessibility of the project's documentation. It refines the core description of the X agent's functionality and simplifies the process for users to acquire necessary API keys, making the setup process smoother for new contributors.

Highlights

  • Project Description Clarification: The project description in the README.md has been updated to more accurately reflect that the X (Twitter) agent acts based on thread context and reasoning, rather than just detecting mentions and routing reasoning.
  • xAI / Grok API Key Instructions Simplification: The instructions for obtaining an xAI / Grok API key have been simplified by removing the prerequisite of an X Premium+ subscription and streamlining the steps from three to two.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the README.md to clarify the project description and simplify API key instructions. My review focuses on improving clarity and consistency. I've pointed out a minor typo in the description and a formatting inconsistency in one of the instructional lists. Applying these suggestions will enhance the readability of the documentation.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request updates the README.md to clarify the project description and simplify the xAI/Grok API key setup instructions. The description now emphasizes that the agent acts based on thread context and reasoning rather than just detecting mentions, and the API key instructions have been streamlined by removing the Premium+ subscription requirement.

Changes:

  • Updated project description to better explain the agent's behavior as acting on context and reasoning
  • Simplified xAI/Grok API key instructions by removing Premium+ subscription requirement

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

README.md Outdated
# MyXstack

This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that detects mentions, pulls thread context, and routes reasoning through Grok via the xMCP server. Follow the phases below to get from zero to a working "tag and watch" prototype.
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The phrasing "acts based on thread context & reasoning, through Grok via the xMCP server" is awkward and unclear. Consider rewording to something clearer like "that acts on thread context and reasoning through Grok via the xMCP server" or "that uses thread context and Grok reasoning via the xMCP server to take actions".

Suggested change
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server.
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that uses thread context and Grok reasoning via the xMCP server to take actions.

Copilot uses AI. Check for mistakes.
README.md Outdated
Comment on lines 23 to 24
. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
. Store the key securely.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list items are using periods instead of numbers. Lines 23-24 should start with "1." and "2." respectively to maintain consistency with all other numbered lists in the README (see lines 8-20, 32-72, etc.). The current format with bare periods creates broken list formatting.

Suggested change
. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
. Store the key securely.
1. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
2. Store the key securely.

Copilot uses AI. Check for mistakes.
README.md Outdated
# MyXstack

This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that detects mentions, pulls thread context, and routes reasoning through Grok via the xMCP server. Follow the phases below to get from zero to a working "tag and watch" prototype.
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an extra space between "that" and "acts". The text should read "agent system that acts" instead of "agent system that acts" (note the double space).

Suggested change
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server.
This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server.

Copilot uses AI. Check for mistakes.
Copilot AI and others added 4 commits January 28, 2026 17:03
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings January 28, 2026 17:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

README.md Outdated
Comment on lines 23 to 24
. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
. Store the key securely.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list items are missing their numbering prefixes. The lines should start with "1." and "2." instead of just "." to maintain proper markdown list formatting.

Suggested change
. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
. Store the key securely.
1. Visit <https://console.x.ai>, open the API keys section, and create a key that starts with `xai-`.
2. Store the key securely.

Copilot uses AI. Check for mistakes.
Copilot AI and others added 2 commits January 28, 2026 17:18
Copilot AI review requested due to automatic review settings January 29, 2026 18:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- name: Basic Syntax Check
run: |
echo "Running syntax validation..."
find . -name "*.js" -o -name "*.py" -o -name "*.ts" | xargs -I {} node -c {} || true
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax check command uses node -c to check JavaScript/TypeScript files, but this will fail for Python files. The command finds .js, .py, and .ts files but only validates them with Node.js. Python files should be checked with a Python syntax checker (like python -m py_compile), and the || true at the end silently ignores all errors, making this check ineffective. Consider separating the validation by file type or removing unsupported file types from the check.

Suggested change
find . -name "*.js" -o -name "*.py" -o -name "*.ts" | xargs -I {} node -c {} || true
js_ts_files=$(find . \( -name "*.js" -o -name "*.ts" \))
if [ -n "$js_ts_files" ]; then
echo "$js_ts_files" | xargs -r -I {} node -c {}
fi
py_files=$(find . -name "*.py")
if [ -n "$py_files" ]; then
echo "$py_files" | xargs -r -I {} python -m py_compile {}
fi

Copilot uses AI. Check for mistakes.
Copilot AI added a commit that referenced this pull request Feb 9, 2026
Copilot AI added a commit that referenced this pull request Feb 9, 2026
- xapi.ts: Use URLSearchParams for mentions URL with since_id support
- xapi.ts: Add Array.isArray() guard before parseThread() in fetchThread
- xapi.ts: Add Array.isArray() guard in searchTweets
- xapi.ts: Change any to unknown in parseThread parameter type
- agent.ts: Process mentions oldest-first and add safe iterator pruning
- grok.ts: Replace any with typed response, fix as any cast
- auto-label.yml: Add permissions: pull-requests: write
- issue-triage.yml: Add permissions: issues: write
- pr-checks.yml: Add permissions: pull-requests: write, fix syntax check
- README.md: Fix double space and improve wording

Co-authored-by: groupthinking <[email protected]>
- Add Array.isArray guard in fetchThread (xapi.ts)
- Use URLSearchParams for mentions URL construction (xapi.ts)
- Add since_id pagination tracking for mentions (xapi.ts)
- Add console.log→stderr redirect for MCP transport (index.ts)
- Add memory pruning with safe iterator for processedMentions (agent.ts)
- Process mentions oldest-first for chronological pruning (agent.ts)
- Replace any with unknown/proper types (xapi.ts, grok.ts)
- Fix CODEOWNERS invalid usernames to @groupthinking
- Add permissions blocks to all workflow files
- Add label existence check in issue-triage workflow

Co-authored-by: groupthinking <[email protected]>
Copilot AI added a commit that referenced this pull request Feb 9, 2026
- Add console.log→stderr redirect with unknown[] type (PR #26)
- Use URLSearchParams for mentions URL + since_id pagination (PR #26)
- Add Array.isArray() guard in fetchThread() (PR #26)
- Add Set pruning with safe { value, done } iterator (PR #26)
- Process mentions oldest-first for chronological pruning (PR #26)
- Use [key: string]: unknown in parseThread, spread sort (PR #26)
- Add mentionPostId param for correct reply targeting (PR #6)
- Fix any type in Grok response parsing (PR #6)
- Fix README broken list numbering (PR #4)

Co-authored-by: groupthinking <[email protected]>
fix: consolidate actionable review feedback from PRs #4, #6, #13, #26
@github-actions
Copy link

github-actions bot commented Feb 9, 2026

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (27244 lines changed)

listener.py Outdated
id=bot_id,
since_id=last_seen_id,
tweet_fields=["created_at", "conversation_id"],
mentions = client.get_users_mentions(

This comment was marked as outdated.

Comment on lines +35 to +42
access_token = os.getenv("X_ACCESS_TOKEN") or os.getenv("X_OAUTH_ACCESS_TOKEN")
access_secret = os.getenv("X_ACCESS_SECRET") or os.getenv("X_OAUTH_ACCESS_TOKEN_SECRET")
return tweepy.Client(
bearer_token=require_env("X_BEARER_TOKEN"),
consumer_key=require_env("X_API_KEY"),
consumer_secret=require_env("X_API_SECRET"),
access_token=require_env("X_OAUTH_ACCESS_TOKEN"),
access_token_secret=require_env("X_OAUTH_ACCESS_TOKEN_SECRET"),
bearer_token=os.getenv("X_BEARER_TOKEN"),
consumer_key=os.getenv("X_API_KEY"),
consumer_secret=os.getenv("X_API_SECRET"),
access_token=access_token,
access_token_secret=access_secret,

This comment was marked as outdated.

Comment on lines +106 to +108
if last_seen:
try:
start_time = datetime.fromisoformat(last_seen)

This comment was marked as outdated.

Comment on lines +115 to +116
while True:
messages = get_messages(agent_id)

This comment was marked as outdated.

- Fix Pydantic v2 deprecations (.dict → .model_dump)
- Add health endpoint to timeline server
- Add Dockerfile, docker-compose.yml, Makefile, .gitignore
- Pin requirements.txt with minimum versions
- Rewrite README as getting-started guide
- Section env.example with comments + missing TS vars
- Move ARCHITECTURE/DEPLOYMENT/USAGE to docs/
- Remove MOLT_STRATEGIC_ANALYSIS.md and IMPLEMENTATION_SUMMARY.md
Copilot AI review requested due to automatic review settings February 12, 2026 11:17
@github-actions
Copy link

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (26757 lines changed)

Comment on lines 145 to 146

# TODO: Replace with Grok invocation via xMCP.
_ = prompt

try:
client.create_tweet(
text="Processing your tag... (full response coming soon)",
in_reply_to_tweet_id=mention.id,
)
except TweepyException as exc:
print(f"Failed to reply to mention {mention.id}: {exc}")
had_failure = True
break

processed_ids.append(int(mention.id))

if processed_ids:
last_seen_id = max(processed_ids)
if not had_failure:
last_checked = datetime.now(timezone.utc)
time.sleep(poll_interval)
start_time = mention.created_at or datetime.now(timezone.utc)

This comment was marked as outdated.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 31 changed files in this pull request and generated 9 comments.


permissions:
contents: read
pull-requests: write
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workflow calls github.rest.issues.createComment, but the workflow permissions do not grant issues: write. This will fail at runtime on GitHub-hosted runners; add issues: write (and keep pull-requests: read/write as needed).

Suggested change
pull-requests: write
pull-requests: write
issues: write

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +41
const allMessages = [...errors, ...warnings];
if (allMessages.length > 0) {
const comment = `## 🔍 PR Validation\n\n${allMessages.join('\n')}`;
await github.rest.issues.createComment({
owner: context.repo.owner,
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job creates a new PR comment on every run when warnings/errors are present, which can spam PRs on synchronize. Consider updating an existing bot comment (e.g., search for a marker header) instead of always creating a new one.

Copilot uses AI. Check for mistakes.
if not had_failure:
last_checked = datetime.now(timezone.utc)
time.sleep(poll_interval)
start_time = mention.created_at or datetime.now(timezone.utc)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating start_time to mention.created_at can lead to duplicate processing (if the API treats start_time as inclusive) or missed mentions when multiple mentions share the same timestamp. Prefer tracking since_id (tweet ID) or advance the timestamp slightly (e.g., +1s) when persisting start_time.

Suggested change
start_time = mention.created_at or datetime.now(timezone.utc)
# Advance the persisted start_time slightly past the mention's created_at
# to avoid duplicate processing when the API treats start_time as inclusive
# and to prevent skipping mentions that share the same timestamp.
if mention.created_at is not None:
start_time = mention.created_at + timedelta(seconds=1)
else:
start_time = datetime.now(timezone.utc)

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +24
stop:
@pkill -f "python server.py" 2>/dev/null || true
@pkill -f "python timeline_server.py" 2>/dev/null || true
@pkill -f "python listener.py" 2>/dev/null || true
@pkill -f "python mcp_dispatcher.py" 2>/dev/null || true
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make stop uses pkill -f "python ...", which can kill unrelated Python processes that happen to match the command line. Consider tracking service PIDs (pidfiles) and killing only those, or rely on Docker Compose for lifecycle management.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +119
while True:
messages = get_messages(agent_id)
for message in messages:
created_at = _parse_time(message.get("created_at"))
if last_seen and created_at and created_at <= last_seen:
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dispatcher loop lacks exception handling around timeline HTTP calls and the xAI streaming call. A single connection error (timeline down, timeout, Grok error) can terminate the process. Add per-message try/except (and log + retry/backoff) so one failure doesn't halt processing.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +5
curl -fsSL https://openclaw.ai/install.sh | bash Learn more →> ## Documentation Index
> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Claude Code to tools via MCP
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This instruction file begins with a curl ... | bash command and includes large chunks of unrelated third‑party content (including prompt-injection style text). Instruction files can be consumed by tooling; please remove this content and replace it with minimal, repo-specific guidance.

Copilot uses AI. Check for mistakes.

permissions:
contents: read
pull-requests: write
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workflow uses github.rest.issues.listLabelsForRepo and github.rest.issues.addLabels, but does not grant issues: write. pull-requests: write is not sufficient for these endpoints; add permissions: issues: write.

Suggested change
pull-requests: write
pull-requests: write
issues: write

Copilot uses AI. Check for mistakes.
Comment on lines 119 to 123
context = mention.text
prompt = f"""
You are an autonomous X agent bot. You were mentioned in this thread:

{context}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README claims the listener "reasons over thread context", but here context is only mention.text and no thread/conversation is fetched. Either fetch thread context before prompting Grok, or adjust the README wording to match the current behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +60
@app.get("/v1/timeline/users/{user_id}/items")
def get_items(user_id: str, status: Optional[str] = None) -> Dict[str, Any]:
items = list_items(user_id, status)
return {"items": items, "count": len(items)}

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All Timeline/A2A endpoints are unauthenticated. Since the README includes public deployment guidance (e.g., Railway), this would expose message injection and timeline manipulation to anyone who can reach the service. Consider adding authentication (shared secret / bearer token), or binding to localhost and documenting required network restrictions.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (26835 lines changed)

Copilot AI review requested due to automatic review settings February 12, 2026 15:33
@github-actions
Copy link

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (26835 lines changed)

@github-actions
Copy link

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (26835 lines changed)

@github-actions
Copy link

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (26849 lines changed)

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 32 changed files in this pull request and generated 6 comments.

Comment on lines +115 to +146
while True:
messages = get_messages(agent_id)
for message in messages:
created_at = _parse_time(message.get("created_at"))
if last_seen and created_at and created_at <= last_seen:
continue
if message.get("type") != "timeline_action":
continue

metadata = message.get("metadata", {})
item_id = metadata.get("timeline_item_id")
action = metadata.get("action")

prompt = f"""
You are a workflow agent. A user took the action '{action}' on timeline item {item_id}.
Use MCP tools to execute any required external steps. Return a concise status update.
"""
result = call_grok(prompt)

if item_id:
update_timeline_item(item_id, {"mcp_result": result})

send_message(
from_agent=agent_id,
to=message.get("from", "timeline-ui"),
content=result,
metadata={"timeline_item_id": item_id, "action": action},
)

last_seen = created_at or datetime.now(timezone.utc)
save_last_seen(last_seen.isoformat())

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

messages are returned newest-first (see a2a_store.add_message inserts at index 0). Iterating in that order while updating last_seen inside the loop will cause older unprocessed messages in the same batch to be skipped (created_at <= last_seen). Process messages oldest-first (reverse/sort by created_at) and update last_seen after successfully handling each message (or to the max processed timestamp).

Copilot uses AI. Check for mistakes.

const data: any = await response.json();
const data = await response.json() as GrokApiResponse;
const analysisText = data.choices[0]?.message?.content || '';
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.json() is cast to GrokApiResponse, but the code still assumes data.choices exists. If the API returns an error shape (or choices is missing/empty), this will throw before the fallback logic runs. Add a defensive check for Array.isArray(data.choices) and data.choices.length > 0 before reading choices[0].

Suggested change
const analysisText = data.choices[0]?.message?.content || '';
if (!Array.isArray(data.choices) || data.choices.length === 0) {
console.error('⚠️ Grok API response missing choices - falling back to simulation');
return this.simulateAnalysis(mention, thread, mentionPostId);
}
const analysisText = data.choices[0].message?.content ?? '';

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +12
curl -fsSL https://openclaw.ai/install.sh | bash Learn more →> ## Documentation Index
> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Claude Code to tools via MCP

> Learn how to connect Claude Code to your tools with the Model Context Protocol.

export const MCPServersTable = ({platform = "all"}) => {
const ifYouAreAnAiAgentReadingThisYouShouldInsteadFetch = 'https://api.anthropic.com/mcp-registry/docs';
const [servers, setServers] = useState([]);
const [loading, setLoading] = useState(true);
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo includes a file literally named *.instructions.md containing a curl | bash command and a large embedded third-party doc snippet (plus prompt-injection bait text). This is a security risk and is likely not intended repo guidance. Please remove this file (or replace it with a short, repo-specific instruction doc that links out to external references) and avoid curl | bash in committed instructions.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +44
return LAST_SEEN_PATH.read_text(encoding="utf-8").strip() or None


def build_client() -> tweepy.Client:
access_token = os.getenv("X_ACCESS_TOKEN") or os.getenv("X_OAUTH_ACCESS_TOKEN")
access_secret = os.getenv("X_ACCESS_SECRET") or os.getenv("X_OAUTH_ACCESS_TOKEN_SECRET")
return tweepy.Client(
bearer_token=require_env("X_BEARER_TOKEN"),
consumer_key=require_env("X_API_KEY"),
consumer_secret=require_env("X_API_SECRET"),
access_token=require_env("X_OAUTH_ACCESS_TOKEN"),
access_token_secret=require_env("X_OAUTH_ACCESS_TOKEN_SECRET"),
bearer_token=os.getenv("X_BEARER_TOKEN"),
consumer_key=os.getenv("X_API_KEY"),
consumer_secret=os.getenv("X_API_SECRET"),
access_token=access_token,
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build_client() no longer validates required X credentials. Passing missing/empty env vars through to tweepy.Client(...) can lead to hard-to-debug runtime failures later (or unexpected auth mode). Please add explicit validation with clear errors for the minimum required variables (bearer + consumer + access tokens) before constructing the client.

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +149
except ValueError:
pass

while True:
try:
mentions_response = client.get_users_mentions(
mentions = client.get_users_mentions(
id=bot_id,
since_id=last_seen_id,
tweet_fields=["created_at", "conversation_id"],
start_time=start_time,
tweet_fields=["conversation_id", "created_at", "author_id", "text"],
)
except TweepyException as exc:
print(f"Failed to fetch mentions: {exc}")
time.sleep(poll_interval)
except TweepyHTTPException as exc:
status_code = getattr(getattr(exc, "response", None), "status_code", None)
if status_code == 402:
# Avoid crash-looping if the X account does not have API credits enabled yet.
print(
f"X API returned 402 Payment Required. Backing off for {PAYMENT_REQUIRED_BACKOFF_SECONDS}s.",
flush=True,
)
time.sleep(PAYMENT_REQUIRED_BACKOFF_SECONDS)
continue
print(f"X API error fetching mentions: {exc}", flush=True)
time.sleep(POLL_SECONDS)
continue
except Exception as exc:
print(f"Unexpected error fetching mentions: {exc}", flush=True)
time.sleep(POLL_SECONDS)
continue

mentions = mentions_response.data or []
processed_ids: list[int] = []
had_failure = False

for mention in reversed(mentions):
if mention.created_at and mention.created_at < last_checked:
processed_ids.append(int(mention.id))
continue
if not mention.conversation_id:
processed_ids.append(int(mention.id))
continue
for mention in mentions.data or []:
context = mention.text
prompt = f"""
You are an autonomous X agent bot. You were mentioned in this thread:

context = fetch_thread_context(client, str(mention.conversation_id))
if context is None:
print(f"Skipping mention {mention.id} due to thread fetch failure.")
had_failure = True
break

prompt = (
"You were tagged here:\n"
f"{context}\n\n"
"Reason through this step-by-step and use X tools via xMCP to respond autonomously.\n"
"Server: http://127.0.0.1:8000/mcp"
)
{context}

# TODO: Replace with Grok invocation via xMCP.
_ = prompt
Analyze the request/intent. Use available tools to respond helpfully.
Always reply directly to the mentioning post. Be concise and actionable.
"""
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main polling loop has no exception handling around get_users_mentions, get_grok_reply, create_tweet, or the timeline POST. Any transient API/network error will crash the process (or the worker thread in main.py). Wrap the loop body in try/except, log the error, and continue with a backoff/sleep so the service stays alive.

Copilot uses AI. Check for mistakes.
Comment on lines 146 to +148

# TODO: Replace with Grok invocation via xMCP.
_ = prompt
Analyze the request/intent. Use available tools to respond helpfully.
Always reply directly to the mentioning post. Be concise and actionable.
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start_time is updated to mention.created_at and then reused for the next poll. Since start_time filtering is inclusive, this can re-fetch the last processed mention and cause duplicate replies/cards after restarts or rate-limit retries. Prefer tracking since_id (tweet ID), or advance the timestamp slightly (e.g., mention.created_at + 1s) when persisting.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants